You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dh...@apache.org on 2015/06/25 05:35:49 UTC

[1/8] camel git commit: CAMEL-8900: Fixed Javadoc parser missing first void method in API Component Framework

Repository: camel
Updated Branches:
  refs/heads/camel-2.14.x dc370b570 -> b508c4dc6
  refs/heads/camel-2.15.x c9f71d519 -> 7e3b35101


CAMEL-8900: Fixed Javadoc parser missing first void method in API Component Framework


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/59ae68db
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/59ae68db
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/59ae68db

Branch: refs/heads/camel-2.15.x
Commit: 59ae68db9f8d624fc0476a4320a2b2d40443d4b4
Parents: c9f71d5
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Wed Jun 24 16:16:13 2015 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Wed Jun 24 20:35:11 2015 -0700

----------------------------------------------------------------------
 .../src/main/java/org/apache/camel/maven/JavadocParser.java    | 5 +++--
 .../test/java/org/apache/camel/maven/JavadocParserTest.java    | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/59ae68db/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
index 706e0b5..b6a1ea2 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
@@ -86,7 +86,6 @@ public class JavadocParser extends Parser {
 
                             final String hrefAttr = (String) attributes.getAttribute(HTML.Attribute.HREF);
                             if (hrefAttr != null && hrefAttr.contains(hrefPattern)) {
-
                                 // unescape HTML
                                 String methodSignature = hrefAttr.substring(hrefAttr.indexOf('#') + 1);
                                 final int firstHyphen = methodSignature.indexOf('-');
@@ -146,7 +145,9 @@ public class JavadocParser extends Parser {
             }
 
             parserState = ParserState.METHOD_SUMMARY;
-        } else if (parserState == ParserState.METHOD_SUMMARY && HTML.Tag.TABLE.equals(tag.getHTMLTag())) {
+        } else if (parserState == ParserState.METHOD_SUMMARY
+            && !methods.isEmpty()
+            && HTML.Tag.TABLE.equals(tag.getHTMLTag())) {
             // end of method summary table
             parserState = ParserState.INIT;
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/59ae68db/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java b/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
index 183ffbb..8ee9e1e 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
@@ -40,16 +40,16 @@ public class JavadocParserTest extends Assert {
 
         htmlParser.parse(new InputStreamReader(new URL(JAVA6_STRING).openStream(), "UTF-8"));
         assertNull("Java6 getErrorMessage", htmlParser.getErrorMessage());
-        assertFalse("Java6 getMethods", htmlParser.getMethods().isEmpty());
+        assertEquals("Java6 getMethods", 65, htmlParser.getMethods().size());
         htmlParser.reset();
 
         htmlParser.parse(new InputStreamReader(new URL(JAVA7_STRING).openStream(), "UTF-8"));
         assertNull("Java7 getErrorMessage", htmlParser.getErrorMessage());
-        assertFalse("Java7 getMethods", htmlParser.getMethods().isEmpty());
+        assertEquals("Java7 getMethods", 65, htmlParser.getMethods().size());
         htmlParser.reset();
 
         htmlParser.parse(new InputStreamReader(new URL(JAVA8_STRING).openStream(), "UTF-8"));
         assertNull("Java8 getErrorMessage", htmlParser.getErrorMessage());
-        assertFalse("Java8 getMethods", htmlParser.getMethods().isEmpty());
+        assertEquals("Java8 getMethods", 67, htmlParser.getMethods().size());
     }
 }


[2/8] camel git commit: CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API

Posted by dh...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java
new file mode 100644
index 0000000..8df7b07
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java
@@ -0,0 +1,285 @@
+/**
+ * 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.salesforce;
+
+import java.io.FileInputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.salesforce.api.SalesforceReportResultsToListConverter;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AsyncReportResults;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.QueryRecordsReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.Report;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportStatusEnum;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.SyncReportResults;
+import org.apache.camel.dataformat.csv.CsvDataFormat;
+import org.apache.commons.csv.CSVFormat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Integration test for Salesforce analytics API endpoints. 
+ */
+@RunWith(Theories.class)
+public class AnalyticsApiIntegrationTest extends AbstractSalesforceTestBase {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AnalyticsApiIntegrationTest.class);
+    private static final int RETRY_DELAY = 5000;
+    private static final int REPORT_RESULT_RETRIES = 5;
+    private static final String[] REPORT_OPTIONS = new String[]{
+        SalesforceReportResultsToListConverter.INCLUDE_HEADERS,
+        SalesforceReportResultsToListConverter.INCLUDE_DETAILS,
+        SalesforceReportResultsToListConverter.INCLUDE_SUMMARY
+    };
+    private static final int NUM_OPTIONS = REPORT_OPTIONS.length;
+    private static final int[] POWERS = new int[] {4, 2, 1};
+
+    private static String[] testReportNames;
+    private boolean bodyMetadata;
+
+    /**
+     * Get test report developer names as data points.
+     * @return test report developer names in test-salesforce-login.properties
+     * @throws Exception
+     */
+    @DataPoints
+    public static String[] getTestReportDeveloperNames() throws Exception {
+        return testReportNames;
+    }
+
+    @BeforeClass
+    public static void getReportNames() throws Exception {
+        // get test report names
+        Properties testProperties = new Properties();
+        testProperties.load(new FileInputStream(LoginConfigHelper.TEST_LOGIN_PROPERTIES));
+
+        Map<String, String> reports = new TreeMap<String, String>();
+        for (Map.Entry<Object, Object> entry : testProperties.entrySet()) {
+            final String key = entry.getKey().toString();
+            if (key.matches("report.[0-9]+")) {
+                reports.put(key, entry.getValue().toString());
+            }
+        }
+        assertFalse("Missing entries report.[0-9]+=<Report DeveloperName> in "
+            + LoginConfigHelper.TEST_LOGIN_PROPERTIES, reports.isEmpty());
+
+        final Collection<String> reportNames = reports.values();
+        testReportNames = reportNames.toArray(new String[reportNames.size()]);
+    }
+
+    @Test
+    public void testGetRecentReports() throws Exception {
+
+        final List recentReports = template().requestBody("direct:getRecentReports", null, List.class);
+
+        assertNotNull("getRecentReports", recentReports);
+        assertFalse("getRecentReports empty", recentReports.isEmpty());
+        LOG.debug("getRecentReports: {}", recentReports);
+    }
+
+    @Theory
+    public void testReport(String reportName) throws Exception {
+
+        log.info("Testing report {}...", reportName);
+
+        // get Report Id
+        final QueryRecordsReport reports = template().requestBody("direct:queryReport",
+            "SELECT Id FROM Report WHERE DeveloperName='" + reportName + "'", QueryRecordsReport.class);
+
+        assertNotNull("query", reports);
+        final List<Report> reportsRecords = reports.getRecords();
+        assertFalse("Report not found", reportsRecords.isEmpty());
+        final String testReportId = reportsRecords.get(0).getId();
+        assertNotNull(testReportId);
+
+        // 1. getReportDescription
+        final ReportDescription reportDescription = template().requestBody("direct:getReportDescription", testReportId,
+            ReportDescription.class);
+
+        assertNotNull("getReportDescriptions", reportDescription);
+        LOG.debug("getReportDescriptions: {}", reportDescription);
+        final ReportMetadata testReportMetadata = reportDescription.getReportMetadata();
+
+        // 2. executeSyncReport
+        // execute with no metadata
+        SyncReportResults reportResults = template().requestBodyAndHeader("direct:executeSyncReport",
+            testReportId, SalesforceEndpointConfig.INCLUDE_DETAILS, Boolean.TRUE, SyncReportResults.class);
+
+        assertNotNull("executeSyncReport", reportResults);
+        LOG.debug("executeSyncReport: {}", reportResults);
+
+        // execute with metadata
+        final Map<String, Object> headers = new HashMap<String, Object>();
+        headers.put(SalesforceEndpointConfig.INCLUDE_DETAILS, Boolean.FALSE);
+        Object body;
+        if (!bodyMetadata) {
+            headers.put(SalesforceEndpointConfig.REPORT_METADATA, testReportMetadata);
+            body = testReportId;
+        } else {
+            body = testReportMetadata;
+        }
+        reportResults = template().requestBodyAndHeaders("direct:executeSyncReport",
+            body, headers, SyncReportResults.class);
+
+        assertNotNull("executeSyncReport with metadata", reportResults);
+        LOG.debug("executeSyncReport with metadata: {}", reportResults);
+
+        // 3. executeAsyncReport
+        // execute with no metadata
+        ReportInstance reportInstance = template().requestBodyAndHeader("direct:executeAsyncReport",
+            testReportId, SalesforceEndpointConfig.INCLUDE_DETAILS, true, ReportInstance.class);
+
+        assertNotNull("executeAsyncReport", reportInstance);
+        LOG.debug("executeAsyncReport: {}", reportInstance);
+
+        // execute with metadata
+        headers.clear();
+        headers.put(SalesforceEndpointConfig.INCLUDE_DETAILS, "true");
+        if (!bodyMetadata) {
+            headers.put(SalesforceEndpointConfig.REPORT_METADATA, testReportMetadata);
+            body = testReportId;
+            bodyMetadata = true;
+        } else {
+            body = testReportMetadata;
+            bodyMetadata = false;
+        }
+        reportInstance = template().requestBodyAndHeaders("direct:executeAsyncReport",
+            body, headers, ReportInstance.class);
+
+        assertNotNull("executeAsyncReport with metadata", reportInstance);
+        LOG.debug("executeAsyncReport with metadata: {}", reportInstance);
+        final String testReportInstanceId = reportInstance.getId();
+
+        // 4. getReportInstances
+        final List reportInstances = template().requestBody("direct:getReportInstances", testReportId, List.class);
+
+        assertNotNull("getReportInstances", reportInstances);
+        assertFalse("getReportInstances empty", reportInstances.isEmpty());
+        LOG.debug("getReportInstances: {}", reportInstances);
+
+        // 5. getReportResults
+        // wait for the report to complete
+        boolean done = false;
+        int tries = 0;
+        AsyncReportResults asyncReportResults = null;
+        while (!done) {
+            asyncReportResults = template().requestBodyAndHeader("direct:getReportResults",
+                testReportId, SalesforceEndpointConfig.INSTANCE_ID, testReportInstanceId, AsyncReportResults.class);
+            done = asyncReportResults != null
+                && (asyncReportResults.getAttributes().getStatus() == ReportStatusEnum.Success
+                    || asyncReportResults.getAttributes().getStatus() == ReportStatusEnum.Error);
+            if (!done) {
+                // avoid flooding calls
+                Thread.sleep(RETRY_DELAY);
+                if (++tries > REPORT_RESULT_RETRIES) {
+                    final long retrySeconds = TimeUnit.SECONDS.convert(tries * RETRY_DELAY, TimeUnit.MILLISECONDS);
+                    fail("Async report result not available in " + retrySeconds + " seconds");
+                }
+            }
+        }
+
+        assertNotNull("getReportResults", asyncReportResults);
+        assertEquals("getReportResults status", ReportStatusEnum.Success,
+            asyncReportResults.getAttributes().getStatus());
+        LOG.debug("getReportResults: {}", asyncReportResults);
+
+        // 6. SalesforceReportResultsConverter tests
+        // defaults
+        String convertResults = template.requestBody("direct:convertResults", asyncReportResults, String.class);
+        assertNotNull("default convertResults", convertResults);
+        LOG.debug("Default options", convertResults);
+        LOG.debug("{}", convertResults);
+
+        // permutations of include details, include headers, include summary
+        final boolean[] values = new boolean[NUM_OPTIONS];
+        final int nIterations = (int) Math.pow(2, NUM_OPTIONS);
+
+        for (int i = 0; i < nIterations; i++) {
+
+            // toggle options
+            for (int j = 0; j < NUM_OPTIONS; j++) {
+                if (i % POWERS[j] == 0) {
+                    values[j] = !values[j];
+                }
+            }
+
+            log.debug("Options {} = {}", REPORT_OPTIONS, values);
+            headers.clear();
+            for (int j = 0; j < REPORT_OPTIONS.length; j++) {
+                headers.put(REPORT_OPTIONS[j], values[j]);
+            }
+            convertResults = template.requestBodyAndHeaders("direct:convertResults", asyncReportResults,
+                headers, String.class);
+
+            assertNotNull("convertResults", convertResults);
+            LOG.debug("{}", convertResults);
+        }
+    }
+
+    @Override
+    protected RouteBuilder doCreateRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+
+                // get Report SObject by DeveloperName
+                from("direct:queryReport")
+                    .to("salesforce:query?sObjectClass=" + QueryRecordsReport.class.getName());
+                
+                from("direct:getRecentReports")
+                    .to("salesforce:getRecentReports");
+
+                from("direct:getReportDescription")
+                    .to("salesforce:getReportDescription");
+                
+                from("direct:executeSyncReport")
+                    .to("salesforce:executeSyncReport");
+                
+                from("direct:executeAsyncReport")
+                    .to("salesforce:executeAsyncReport?includeDetails=true");
+                
+                from("direct:getReportInstances")
+                    .to("salesforce:getReportInstances");
+                
+                from("direct:getReportResults")
+                    .to("salesforce:getReportResults");
+
+                CsvDataFormat csv = new CsvDataFormat(CSVFormat.EXCEL);
+
+                // type converter test
+                from("direct:convertResults")
+                    .convertBodyTo(List.class)
+                    .marshal(csv);
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
index f136a33..28c6a5b 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
@@ -26,7 +26,7 @@ import org.junit.Assert;
 
 public class LoginConfigHelper extends Assert {
 
-    private static final String TEST_LOGIN_PROPERTIES = "../test-salesforce-login.properties";
+    protected static final String TEST_LOGIN_PROPERTIES = "../test-salesforce-login.properties";
 
     public static SalesforceLoginConfig getLoginConfig() throws IOException {
 


[3/8] camel git commit: CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API

Posted by dh...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java
new file mode 100644
index 0000000..b1f039b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java
@@ -0,0 +1,55 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results extended metadata.
+ */
+public class ReportExtendedMetadata extends AbstractDTOBase {
+
+    private Map<String, GroupingColumnInfo> groupingColumnInfo;
+    private Map<String, DetailColumnInfo> detailColumnInfo;
+    private Map<String, AggregateColumnInfo> aggregateColumnInfo;
+
+    public Map<String, GroupingColumnInfo> getGroupingColumnInfo() {
+        return groupingColumnInfo;
+    }
+
+    public void setGroupingColumnInfo(Map<String, GroupingColumnInfo> groupingColumnInfo) {
+        this.groupingColumnInfo = groupingColumnInfo;
+    }
+
+    public Map<String, DetailColumnInfo> getDetailColumnInfo() {
+        return detailColumnInfo;
+    }
+
+    public void setDetailColumnInfo(Map<String, DetailColumnInfo> detailColumnInfo) {
+        this.detailColumnInfo = detailColumnInfo;
+    }
+
+    public Map<String, AggregateColumnInfo> getAggregateColumnInfo() {
+        return aggregateColumnInfo;
+    }
+
+    public void setAggregateColumnInfo(Map<String, AggregateColumnInfo> aggregateColumnInfo) {
+        this.aggregateColumnInfo = aggregateColumnInfo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java
new file mode 100644
index 0000000..bf600ae
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results fact with details.
+ */
+public class ReportFactWithDetails extends AbstractDTOBase {
+
+    private ReportRow[] rows;
+    private SummaryValue[] aggregates;
+
+    public ReportRow[] getRows() {
+        return rows;
+    }
+
+    public void setRows(ReportRow[] rows) {
+        this.rows = rows;
+    }
+
+    public SummaryValue[] getAggregates() {
+        return aggregates;
+    }
+
+    public void setAggregates(SummaryValue[] aggregates) {
+        this.aggregates = aggregates;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java
new file mode 100644
index 0000000..17aa9cf
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java
@@ -0,0 +1,53 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report filter details DTO.
+ */
+public class ReportFilter extends AbstractDTOBase {
+
+    private String value;
+    private String column;
+    private String operator;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getColumn() {
+        return column;
+    }
+
+    public void setColumn(String column) {
+        this.column = column;
+    }
+
+    public String getOperator() {
+        return operator;
+    }
+
+    public void setOperator(String operator) {
+        this.operator = operator;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java
new file mode 100644
index 0000000..744b236
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java
@@ -0,0 +1,24 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report format enumeration.
+ */
+public enum ReportFormatEnum {
+    TABULAR, SUMMARY, MATRIX
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java
new file mode 100644
index 0000000..f69ae8d
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java
@@ -0,0 +1,90 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+import org.joda.time.DateTime;
+
+/**
+ * Report instance DTO.
+ */
+public class ReportInstance extends AbstractDTOBase {
+
+    private String id;
+    private ReportStatusEnum status;
+    private String url;
+    private String ownerId;
+    private Boolean hasDetailRows;
+    private DateTime completionDate;
+    private DateTime requestDate;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public ReportStatusEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(ReportStatusEnum status) {
+        this.status = status;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getOwnerId() {
+        return ownerId;
+    }
+
+    public void setOwnerId(String ownerId) {
+        this.ownerId = ownerId;
+    }
+
+    public Boolean getHasDetailRows() {
+        return hasDetailRows;
+    }
+
+    public void setHasDetailRows(Boolean hasDetailRows) {
+        this.hasDetailRows = hasDetailRows;
+    }
+
+    public DateTime getCompletionDate() {
+        return completionDate;
+    }
+
+    public void setCompletionDate(DateTime completionDate) {
+        this.completionDate = completionDate;
+    }
+
+    public DateTime getRequestDate() {
+        return requestDate;
+    }
+
+    public void setRequestDate(DateTime requestDate) {
+        this.requestDate = requestDate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java
new file mode 100644
index 0000000..1ad0cff
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java
@@ -0,0 +1,143 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report metadata DTO.
+ */
+public class ReportMetadata extends AbstractDTOBase {
+
+    private String name;
+    private String id;
+    private String currency;
+    private ReportFormatEnum reportFormat;
+    private String developerName;
+    private ReportType reportType;
+    private String[] aggregates;
+    private GroupingInfo[] groupingsDown;
+    private GroupingInfo[] groupingsAcross;
+    private String reportBooleanFilter;
+    private ReportFilter[] reportFilters;
+    private String[] detailColumns;
+    private String[] historicalSnapshotDates;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    public void setCurrency(String currency) {
+        this.currency = currency;
+    }
+
+    public ReportFormatEnum getReportFormat() {
+        return reportFormat;
+    }
+
+    public void setReportFormat(ReportFormatEnum reportFormat) {
+        this.reportFormat = reportFormat;
+    }
+
+    public String getDeveloperName() {
+        return developerName;
+    }
+
+    public void setDeveloperName(String developerName) {
+        this.developerName = developerName;
+    }
+
+    public ReportType getReportType() {
+        return reportType;
+    }
+
+    public void setReportType(ReportType reportType) {
+        this.reportType = reportType;
+    }
+
+    public String[] getAggregates() {
+        return aggregates;
+    }
+
+    public void setAggregates(String[] aggregates) {
+        this.aggregates = aggregates;
+    }
+
+    public GroupingInfo[] getGroupingsDown() {
+        return groupingsDown;
+    }
+
+    public void setGroupingsDown(GroupingInfo[] groupingsDown) {
+        this.groupingsDown = groupingsDown;
+    }
+
+    public GroupingInfo[] getGroupingsAcross() {
+        return groupingsAcross;
+    }
+
+    public void setGroupingsAcross(GroupingInfo[] groupingsAcross) {
+        this.groupingsAcross = groupingsAcross;
+    }
+
+    public String getReportBooleanFilter() {
+        return reportBooleanFilter;
+    }
+
+    public void setReportBooleanFilter(String reportBooleanFilter) {
+        this.reportBooleanFilter = reportBooleanFilter;
+    }
+
+    public ReportFilter[] getReportFilters() {
+        return reportFilters;
+    }
+
+    public void setReportFilters(ReportFilter[] reportFilters) {
+        this.reportFilters = reportFilters;
+    }
+
+    public String[] getDetailColumns() {
+        return detailColumns;
+    }
+
+    public void setDetailColumns(String[] detailColumns) {
+        this.detailColumns = detailColumns;
+    }
+
+    public String[] getHistoricalSnapshotDates() {
+        return historicalSnapshotDates;
+    }
+
+    public void setHistoricalSnapshotDates(String[] historicalSnapshotDates) {
+        this.historicalSnapshotDates = historicalSnapshotDates;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java
new file mode 100644
index 0000000..5349dcc
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java
@@ -0,0 +1,35 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Reports fact map row.
+ */
+public class ReportRow extends AbstractDTOBase {
+
+    private SummaryValue[] dataCells;
+
+    public SummaryValue[] getDataCells() {
+        return dataCells;
+    }
+
+    public void setDataCells(SummaryValue[] dataCells) {
+        this.dataCells = dataCells;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java
new file mode 100644
index 0000000..871aa8e
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java
@@ -0,0 +1,24 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report status enumeration.
+ */
+public enum ReportStatusEnum {
+    New, Success, Running, Error
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java
new file mode 100644
index 0000000..9fd8b90
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type DTO.
+ */
+public class ReportType extends AbstractDTOBase {
+
+    private String type;
+    private String label;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java
new file mode 100644
index 0000000..b1f933b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java
@@ -0,0 +1,62 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report categories columns.
+ */
+public class ReportTypeColumn extends AbstractDTOBase {
+
+    private String label;
+    private FilterValue[] filterValues;
+    private String dataType;
+    private Boolean filterable;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public FilterValue[] getFilterValues() {
+        return filterValues;
+    }
+
+    public void setFilterValues(FilterValue[] filterValues) {
+        this.filterValues = filterValues;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public Boolean getFilterable() {
+        return filterable;
+    }
+
+    public void setFilterable(Boolean filterable) {
+        this.filterable = filterable;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.java
new file mode 100644
index 0000000..fcd5c49
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.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.component.salesforce.api.dto.analytics.reports;
+
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type metadata categories DTO.
+ */
+public class ReportTypeColumnCategory extends AbstractDTOBase {
+
+    private String label;
+    private Map<String, ReportTypeColumn> columns;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public Map<String, ReportTypeColumn> getColumns() {
+        return columns;
+    }
+
+    public void setColumns(Map<String, ReportTypeColumn> columns) {
+        this.columns = columns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java
new file mode 100644
index 0000000..9d849c8
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java
@@ -0,0 +1,47 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report description report type DTO.
+ */
+public class ReportTypeMetadata extends AbstractDTOBase {
+
+    private ReportTypeColumnCategory[] categories;
+    private Map<String, List<FilterOperator>> dataTypeFilterOperatorMap;
+
+    public ReportTypeColumnCategory[] getCategories() {
+        return categories;
+    }
+
+    public void setCategories(ReportTypeColumnCategory[] categories) {
+        this.categories = categories;
+    }
+
+    public Map<String, List<FilterOperator>> getDataTypeFilterOperatorMap() {
+        return dataTypeFilterOperatorMap;
+    }
+
+    public void setDataTypeFilterOperatorMap(Map<String, List<FilterOperator>> dataTypeFilterOperatorMap) {
+        this.dataTypeFilterOperatorMap = dataTypeFilterOperatorMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java
new file mode 100644
index 0000000..34127c7
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java
@@ -0,0 +1,58 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+
+/**
+ * Report results summary value DTO for data cells and aggregates.
+ */
+public class SummaryValue extends AbstractDTOBase {
+
+    public static final String VALUE_FIELD = "value";
+
+    private String label;
+
+    private Object value;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * Helper method for JSON un-marshaling.
+     * @param name field name, MUST be "value"
+     * @param value field value
+     * @throws java.lang.IllegalArgumentException if field name is not "value"
+     */
+    @JsonAnySetter
+    public void setAny(String name, Object value) throws IllegalArgumentException {
+        if (!VALUE_FIELD.equals(name)) {
+            throw new IllegalArgumentException(name);
+        }
+        this.value = value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.java
new file mode 100644
index 0000000..b2cc08d
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.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.component.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report results Attributes.
+ */
+public class SyncAttributes extends AbstractAttributesBase {
+
+    private String describeUrl;
+    private String instancesUrl;
+
+    public String getDescribeUrl() {
+        return describeUrl;
+    }
+
+    public void setDescribeUrl(String describeUrl) {
+        this.describeUrl = describeUrl;
+    }
+
+    public String getInstancesUrl() {
+        return instancesUrl;
+    }
+
+    public void setInstancesUrl(String instancesUrl) {
+        this.instancesUrl = instancesUrl;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java
new file mode 100644
index 0000000..dead5e9
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java
@@ -0,0 +1,34 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Sync Report results DTO.
+ */
+public class SyncReportResults extends AbstractReportResultsBase {
+
+    private SyncAttributes attributes;
+
+    public SyncAttributes getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(SyncAttributes attributes) {
+        this.attributes = attributes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
index a5b7893..efe09ce 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
@@ -49,7 +49,15 @@ public enum OperationName {
     GET_RESULTS("getResults"),
     CREATE_BATCH_QUERY("createBatchQuery"),
     GET_QUERY_RESULT_IDS("getQueryResultIds"),
-    GET_QUERY_RESULT("getQueryResult");
+    GET_QUERY_RESULT("getQueryResult"),
+    
+    // analytics API
+    GET_RECENT_REPORTS("getRecentReports"),
+    GET_REPORT_DESCRIPTION("getReportDescription"),
+    EXECUTE_SYNCREPORT("executeSyncReport"),
+    EXECUTE_ASYNCREPORT("executeAsyncReport"),
+    GET_REPORT_INSTANCES("getReportInstances"),
+    GET_REPORT_RESULTS("getReportResults");
 
     private final String value;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java
new file mode 100644
index 0000000..b40c8bb
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java
@@ -0,0 +1,71 @@
+/**
+ * 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.salesforce.internal.client;
+
+import java.util.List;
+
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AbstractReportResultsBase;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.RecentReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+
+/**
+ * Client interface for Analytics API.
+ */
+public interface AnalyticsApiClient {
+
+    // Report operations
+
+    public interface RecentReportsResponseCallback {
+        void onResponse(List<RecentReport> reportDescription, SalesforceException ex);
+    }
+
+    public interface ReportDescriptionResponseCallback {
+        void onResponse(ReportDescription reportDescription, SalesforceException ex);
+    }
+
+    public interface ReportResultsResponseCallback {
+        void onResponse(AbstractReportResultsBase reportResults, SalesforceException ex);
+    }
+
+    public interface ReportInstanceResponseCallback {
+        void onResponse(ReportInstance reportInstance, SalesforceException ex);
+    }
+
+    public interface ReportInstanceListResponseCallback {
+        void onResponse(List<ReportInstance> reportInstances, SalesforceException ex);
+    }
+
+    void getRecentReports(RecentReportsResponseCallback callback);
+
+    void getReportDescription(String reportId,
+                              ReportDescriptionResponseCallback callback);
+
+    void executeSyncReport(String reportId, Boolean includeDetails, ReportMetadata reportFilter,
+                           ReportResultsResponseCallback callback);
+
+    void executeAsyncReport(String reportId, Boolean includeDetails, ReportMetadata reportFilter,
+                           ReportInstanceResponseCallback callback);
+
+    void getReportInstances(String reportId,
+                           ReportInstanceListResponseCallback callback);
+
+    void getReportResults(String reportId, String instanceId,
+                           ReportResultsResponseCallback callback);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java
new file mode 100644
index 0000000..1041f7f
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java
@@ -0,0 +1,339 @@
+/**
+ * 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.salesforce.internal.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.RestError;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AsyncReportResults;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.RecentReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.SyncReportResults;
+import org.apache.camel.component.salesforce.internal.SalesforceSession;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+import org.eclipse.jetty.util.StringUtil;
+
+/**
+ * Default implementation of {@link org.apache.camel.component.salesforce.internal.client.AnalyticsApiClient}.
+ */
+public class DefaultAnalyticsApiClient extends AbstractClientBase implements AnalyticsApiClient {
+
+    private static final String TOKEN_PREFIX = "Bearer ";
+    private static final String INCLUDE_DETAILS_QUERY_PARAM = "?includeDetails=";
+    private ObjectMapper objectMapper;
+
+
+    public DefaultAnalyticsApiClient(String version, SalesforceSession session, HttpClient httpClient) throws SalesforceException {
+        super(version, session, httpClient);
+
+        objectMapper = new ObjectMapper();
+    }
+
+    @Override
+    public void getRecentReports(final RecentReportsResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET, reportsUrl());
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public void onResponse(InputStream response, SalesforceException ex) {
+                List<RecentReport> recentReports = null;
+                if (response != null) {
+                    try {
+                        recentReports = unmarshalResponse(response, contentExchange,
+                            new TypeReference<List<RecentReport>>() {
+                            }
+                        );
+                    } catch (SalesforceException e) {
+                        ex = e;
+                    }
+                }
+                callback.onResponse(recentReports, ex);
+            }
+        });
+    }
+
+    @Override
+    public void getReportDescription(String reportId, final ReportDescriptionResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET, reportsDescribeUrl(reportId));
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                ReportDescription reportDescription = null;
+                try {
+                    reportDescription = unmarshalResponse(response, contentExchange, ReportDescription.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportDescription, ex);
+            }
+        });
+    }
+
+    @Override
+    public void executeSyncReport(String reportId, Boolean includeDetails, ReportMetadata reportMetadata,
+                                  final ReportResultsResponseCallback callback) {
+
+        final boolean useGet = reportMetadata == null;
+        final ContentExchange contentExchange = getContentExchange(
+            useGet ? HttpMethods.GET : HttpMethods.POST, reportsUrl(reportId, includeDetails));
+
+        // set POST data
+        if (!useGet) {
+            try {
+                // wrap reportMetadata in a map
+                final HashMap<String, Object> request = new HashMap<String, Object>();
+                request.put("reportMetadata", reportMetadata);
+                marshalRequest(request, contentExchange);
+            } catch (SalesforceException e) {
+                callback.onResponse(null, e);
+                return;
+            }
+        }
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                SyncReportResults reportResults = null;
+                try {
+                    reportResults = unmarshalResponse(response, contentExchange, SyncReportResults.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportResults, ex);
+            }
+        });
+    }
+
+    @Override
+    public void executeAsyncReport(String reportId, Boolean includeDetails, ReportMetadata reportMetadata,
+                                   final ReportInstanceResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.POST,
+            reportInstancesUrl(reportId, includeDetails));
+
+        // set POST data
+        if (reportMetadata != null) {
+            try {
+                // wrap reportMetadata in a map
+                final HashMap<String, Object> request = new HashMap<String, Object>();
+                request.put("reportMetadata", reportMetadata);
+                marshalRequest(request, contentExchange);
+            } catch (SalesforceException e) {
+                callback.onResponse(null, e);
+                return;
+            }
+        }
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                ReportInstance reportInstance = null;
+                try {
+                    reportInstance = unmarshalResponse(response, contentExchange, ReportInstance.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportInstance, ex);
+            }
+        });
+    }
+
+    @Override
+    public void getReportInstances(String reportId, final ReportInstanceListResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET, reportInstancesUrl(reportId));
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public void onResponse(InputStream response, SalesforceException ex) {
+                List<ReportInstance> reportInstances = null;
+                if (response != null) {
+                    try {
+                        reportInstances = unmarshalResponse(response, contentExchange,
+                            new TypeReference<List<ReportInstance>>() {
+                            }
+                        );
+                    } catch (SalesforceException e) {
+                        ex = e;
+                    }
+                }
+                callback.onResponse(reportInstances, ex);
+            }
+        });
+    }
+
+    @Override
+    public void getReportResults(String reportId, String instanceId, final ReportResultsResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET,
+            reportInstancesUrl(reportId, instanceId));
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                AsyncReportResults reportResults = null;
+                try {
+                    reportResults = unmarshalResponse(response, contentExchange, AsyncReportResults.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportResults, ex);
+            }
+        });
+    }
+
+    private String reportsUrl() {
+        // NOTE the prefix 'v' for the version number
+        return instanceUrl + "/services/data/v" + version + "/analytics/reports";
+    }
+
+    private String reportsDescribeUrl(String reportId) {
+        return reportsUrl(reportId) + "/describe";
+    }
+
+    private String reportsUrl(String reportId) {
+        return reportsUrl() +  "/" + reportId;
+    }
+
+    private String reportsUrl(String reportId, Boolean includeDetails) {
+        return includeDetails == null ? reportsUrl(reportId)
+                : reportsUrl(reportId) + INCLUDE_DETAILS_QUERY_PARAM + includeDetails;
+    }
+
+    private String reportInstancesUrl(String reportId) {
+        return reportsUrl(reportId) + "/instances";
+    }
+
+    private String reportInstancesUrl(String reportId, Boolean includeDetails) {
+        return includeDetails == null ? reportInstancesUrl(reportId)
+            : reportInstancesUrl(reportId) + INCLUDE_DETAILS_QUERY_PARAM + includeDetails;
+    }
+
+    private String reportInstancesUrl(String reportId, String instanceId) {
+        return reportInstancesUrl(reportId) + "/" + instanceId;
+    }
+
+    @Override
+    protected void setAccessToken(HttpExchange httpExchange) {
+        httpExchange.setRequestHeader(HttpHeaders.AUTHORIZATION, TOKEN_PREFIX + accessToken);
+    }
+
+    @Override
+    protected SalesforceException createRestException(ContentExchange httpExchange, String reason) {
+        final int statusCode = httpExchange.getResponseStatus();
+        String responseContent = null;
+        try {
+            responseContent = httpExchange.getResponseContent();
+            if (responseContent != null) {
+                // unmarshal RestError
+                final List<RestError> errors = objectMapper.readValue(responseContent,
+                    new TypeReference<List<RestError>>() {
+                    });
+                return new SalesforceException(errors, statusCode);
+            }
+        } catch (UnsupportedEncodingException e) {
+            // log and ignore
+            String msg = "Unexpected Error parsing JSON error response body + ["
+                + responseContent + "] : " + e.getMessage();
+            log.warn(msg, e);
+        } catch (IOException e) {
+            // log and ignore
+            String msg = "Unexpected Error parsing JSON error response body + ["
+                + responseContent + "] : " + e.getMessage();
+            log.warn(msg, e);
+        }
+
+        // just report HTTP status info
+        return new SalesforceException("Unexpected error: " + reason + ", with content: " + responseContent,
+            statusCode);
+    }
+
+    @Override
+    protected void doHttpRequest(ContentExchange request, ClientResponseCallback callback) {
+
+        // set access token for all requests
+        setAccessToken(request);
+
+        // set request and response content type and charset, which is always JSON for analytics API
+        request.setRequestHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_UTF8);
+        request.setRequestHeader(HttpHeaders.ACCEPT, APPLICATION_JSON_UTF8);
+        request.setRequestHeader(HttpHeaders.ACCEPT_CHARSET, StringUtil.__UTF8);
+
+        super.doHttpRequest(request, callback);
+    }
+
+    private void marshalRequest(Object input, ContentExchange request) throws SalesforceException {
+        try {
+            request.setRequestContent(new ByteArrayBuffer(objectMapper.writeValueAsBytes(input)));
+        } catch (IOException e) {
+            throw new SalesforceException(
+                String.format("Error marshaling request for {%s:%s} : %s",
+                    request.getMethod(), request.getRequestURI(), e.getMessage()),
+                e);
+        }
+    }
+
+    private <T> T unmarshalResponse(InputStream response, ContentExchange request,
+                                      TypeReference<T> responseTypeReference)
+        throws SalesforceException {
+
+        try {
+            return objectMapper.readValue(response, responseTypeReference);
+        } catch (IOException e) {
+            throw new SalesforceException(
+                String.format("Error unmarshaling response {%s:%s} : %s",
+                    request.getMethod(), request.getRequestURI(), e.getMessage()),
+                e);
+        }
+    }
+
+    private <T> T unmarshalResponse(InputStream response, ContentExchange request, Class<T> responseClass)
+        throws SalesforceException {
+
+        if (response == null) {
+            return null;
+        }
+
+        try {
+            return objectMapper.readValue(response, responseClass);
+        } catch (IOException e) {
+            throw new SalesforceException(
+                String.format("Error unmarshaling response {%s:%s} : %s",
+                    request.getMethod(), request.getRequestURI(), e.getMessage()),
+                e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
index 834ea51..352005a 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
@@ -64,7 +64,7 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor
 
         final PayloadFormat payloadFormat = endpoint.getConfiguration().getFormat();
 
-        this.restClient = new DefaultRestClient(httpClient, endpointConfigMap.get(API_VERSION),
+        this.restClient = new DefaultRestClient(httpClient, (String) endpointConfigMap.get(API_VERSION),
                 payloadFormat, session);
 
         this.classMap = endpoint.getComponent().getClassMap();
@@ -151,19 +151,19 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor
                 processApexCall(exchange, callback);
                 break;
             default:
-                throw new SalesforceException("Unknow operation name: " + operationName, null);
+                throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
             }
         } catch (SalesforceException e) {
             exchange.setException(new SalesforceException(
                     String.format("Error processing %s: [%s] \"%s\"",
-                            operationName, e.getStatusCode(), e.getMessage()),
+                            operationName.value(), e.getStatusCode(), e.getMessage()),
                     e));
             callback.done(true);
             return true;
         } catch (RuntimeException e) {
             exchange.setException(new SalesforceException(
                     String.format("Unexpected Error processing %s: \"%s\"",
-                            operationName, e.getMessage()),
+                            operationName.value(), e.getMessage()),
                     e));
             callback.done(true);
             return true;
@@ -446,7 +446,7 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor
     private void processQuery(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
         final String sObjectQuery = getParameter(SOBJECT_QUERY, exchange, USE_BODY, NOT_OPTIONAL);
 
-        // use sObject name to load class
+        // use custom response class property
         setResponseClass(exchange, null);
 
         restClient.query(sObjectQuery, new RestClient.ResponseCallback() {

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
index db5c66b..151d24d 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
@@ -20,6 +20,8 @@ import java.util.Map;
 
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.component.salesforce.SalesforceComponent;
 import org.apache.camel.component.salesforce.SalesforceEndpoint;
 import org.apache.camel.component.salesforce.api.SalesforceException;
@@ -39,7 +41,7 @@ public abstract class AbstractSalesforceProcessor implements SalesforceProcessor
     protected final Logger log = LoggerFactory.getLogger(this.getClass());
 
     protected final SalesforceEndpoint endpoint;
-    protected final Map<String, String> endpointConfigMap;
+    protected final Map<String, Object> endpointConfigMap;
 
     protected final OperationName operationName;
     protected final SalesforceSession session;
@@ -59,24 +61,65 @@ public abstract class AbstractSalesforceProcessor implements SalesforceProcessor
     public abstract boolean process(Exchange exchange, AsyncCallback callback);
 
     /**
-     * Gets value for a parameter from header, endpoint config, or exchange body (optional).
+     * Gets String value for a parameter from header, endpoint config, or exchange body (optional).
      *
-     * @param exchange      exchange to inspect
-     * @param convertInBody converts In body to String value if true
-     * @param propName      name of property
-     * @param optional      if {@code true} returns null, otherwise throws RestException
+     * @param exchange          exchange to inspect
+     * @param convertInBody     converts In body to String value if true
+     * @param propName          name of property
+     * @param optional          if {@code true} returns null, otherwise throws RestException
      * @return value of property, or {@code null} for optional parameters if not found.
      * @throws org.apache.camel.component.salesforce.api.SalesforceException
-     *          if the property can't be found.
+     *          if the property can't be found or on conversion errors.
      */
     protected final String getParameter(String propName, Exchange exchange, boolean convertInBody, boolean optional) throws SalesforceException {
-        String propValue = exchange.getIn().getHeader(propName, String.class);
-        propValue = propValue == null ? endpointConfigMap.get(propName) : propValue;
-        propValue = (propValue == null && convertInBody) ? exchange.getIn().getBody(String.class) : propValue;
+        return getParameter(propName, exchange, convertInBody, optional, String.class);
+    }
+
+    /**
+     * Gets value for a parameter from header, endpoint config, or exchange body (optional).
+     *
+     * @param exchange          exchange to inspect
+     * @param convertInBody     converts In body to parameterClass value if true
+     * @param propName          name of property
+     * @param optional          if {@code true} returns null, otherwise throws RestException
+     * @param parameterClass    parameter type
+     * @return value of property, or {@code null} for optional parameters if not found.
+     * @throws org.apache.camel.component.salesforce.api.SalesforceException
+     *          if the property can't be found or on conversion errors.
+     */
+    protected final <T> T getParameter(String propName, Exchange exchange, boolean convertInBody, boolean optional,
+                                       Class<T> parameterClass) throws SalesforceException {
+
+        final Message in = exchange.getIn();
+        T propValue = in.getHeader(propName, parameterClass);
+
+        if (propValue == null) {
+            // check if type conversion failed
+            if (in.getHeader(propName) != null) {
+                throw new IllegalArgumentException("Header " + propName
+                    + " could not be converted to type " + parameterClass.getName());
+            }
+
+            final Object value = endpointConfigMap.get(propName);
+
+            if (value == null || parameterClass.isInstance(value)) {
+                propValue = parameterClass.cast(value);
+            } else {
+
+                try {
+                    propValue = exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterClass, value);
+                } catch (NoTypeConversionAvailableException e) {
+                    throw new SalesforceException(e);
+                }
+            }
+        }
+
+        propValue = (propValue == null && convertInBody) ? in.getBody(parameterClass) : propValue;
 
         // error if property was not set
         if (propValue == null && !optional) {
-            String msg = "Missing property " + propName;
+            String msg = "Missing property " + propName
+                + (convertInBody ? ", message body could not be converted to type " + parameterClass.getName() : "");
             throw new SalesforceException(msg, null);
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
new file mode 100644
index 0000000..846bd62
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
@@ -0,0 +1,227 @@
+/**
+ * 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.salesforce.internal.processor;
+
+import java.util.List;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.salesforce.SalesforceEndpoint;
+import org.apache.camel.component.salesforce.SalesforceEndpointConfig;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AbstractReportResultsBase;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.RecentReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.internal.client.AnalyticsApiClient;
+import org.apache.camel.component.salesforce.internal.client.DefaultAnalyticsApiClient;
+import org.apache.camel.util.ServiceHelper;
+
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.INCLUDE_DETAILS;
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.INSTANCE_ID;
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.REPORT_ID;
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.REPORT_METADATA;
+
+/**
+ * Exchange processor for Analytics API.
+ */
+public class AnalyticsApiProcessor extends AbstractSalesforceProcessor {
+
+    private AnalyticsApiClient analyticsClient;
+
+    public AnalyticsApiProcessor(SalesforceEndpoint endpoint) throws SalesforceException {
+        super(endpoint);
+
+        this.analyticsClient = new DefaultAnalyticsApiClient(
+            (String) endpointConfigMap.get(SalesforceEndpointConfig.API_VERSION), session, httpClient);
+    }
+
+    @Override
+    public boolean process(final Exchange exchange, final AsyncCallback callback) {
+        boolean done = false;
+
+        try {
+            switch (operationName) {
+            case GET_RECENT_REPORTS:
+                processGetRecentReports(exchange, callback);
+                break;
+            case GET_REPORT_DESCRIPTION:
+                processGetReportDescription(exchange, callback);
+                break;
+            case EXECUTE_SYNCREPORT:
+                processExecuteSyncReport(exchange, callback);
+                break;
+            case EXECUTE_ASYNCREPORT:
+                processExecuteAsyncReport(exchange, callback);
+                break;
+            case GET_REPORT_INSTANCES:
+                processGetReportInstances(exchange, callback);
+                break;
+            case GET_REPORT_RESULTS:
+                processGetReportResults(exchange, callback);
+                break;
+            default:
+                throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
+            }
+        } catch (SalesforceException e) {
+            exchange.setException(new SalesforceException(
+                    String.format("Error processing %s: [%s] \"%s\"",
+                            operationName.value(), e.getStatusCode(), e.getMessage()), e));
+            callback.done(true);
+            done = true;
+        } catch (RuntimeException e) {
+            exchange.setException(new SalesforceException(
+                    String.format("Unexpected Error processing %s: \"%s\"",
+                            operationName.value(), e.getMessage()), e));
+            callback.done(true);
+            done = true;
+        }
+
+        // continue routing asynchronously if false
+        return done;
+    }
+
+    private void processGetRecentReports(final Exchange exchange, final AsyncCallback callback) {
+
+        analyticsClient.getRecentReports(new AnalyticsApiClient.RecentReportsResponseCallback() {
+            @Override
+            public void onResponse(List<RecentReport> reportDescription, SalesforceException ex) {
+                processResponse(exchange, reportDescription, ex, callback);
+            }
+        });
+    }
+
+    private void processGetReportDescription(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        final String reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+
+        analyticsClient.getReportDescription(reportId, new AnalyticsApiClient.ReportDescriptionResponseCallback() {
+            @Override
+            public void onResponse(ReportDescription reportDescription, SalesforceException ex) {
+                processResponse(exchange, reportDescription, ex, callback);
+            }
+        });
+    }
+
+    private void processExecuteSyncReport(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        String reportId;
+        final Boolean includeDetails = getParameter(INCLUDE_DETAILS, exchange, IGNORE_BODY, IS_OPTIONAL, Boolean.class);
+
+        // try getting report metadata from body first
+        ReportMetadata reportMetadata = exchange.getIn().getBody(ReportMetadata.class);
+        if (reportMetadata != null) {
+            reportId = reportMetadata.getId();
+            if (reportId == null) {
+                reportId = getParameter(REPORT_ID, exchange, IGNORE_BODY, NOT_OPTIONAL);
+            }
+        } else {
+            reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+            reportMetadata = getParameter(REPORT_METADATA, exchange, IGNORE_BODY, IS_OPTIONAL,
+                ReportMetadata.class);
+        }
+
+        analyticsClient.executeSyncReport(reportId, includeDetails, reportMetadata,
+            new AnalyticsApiClient.ReportResultsResponseCallback() {
+                @Override
+                public void onResponse(AbstractReportResultsBase reportResults, SalesforceException ex) {
+                    processResponse(exchange, reportResults, ex, callback);
+                }
+            });
+    }
+
+    private void processExecuteAsyncReport(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        String reportId;
+        final Boolean includeDetails = getParameter(INCLUDE_DETAILS, exchange, IGNORE_BODY, IS_OPTIONAL, Boolean.class);
+
+        // try getting report metadata from body first
+        ReportMetadata reportMetadata = exchange.getIn().getBody(ReportMetadata.class);
+        if (reportMetadata != null) {
+            reportId = reportMetadata.getId();
+            if (reportId == null) {
+                reportId = getParameter(REPORT_ID, exchange, IGNORE_BODY, NOT_OPTIONAL);
+            }
+        } else {
+            reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+            reportMetadata = getParameter(REPORT_METADATA, exchange, IGNORE_BODY, IS_OPTIONAL,
+                ReportMetadata.class);
+        }
+
+        analyticsClient.executeAsyncReport(reportId, includeDetails, reportMetadata,
+            new AnalyticsApiClient.ReportInstanceResponseCallback() {
+                @Override
+                public void onResponse(ReportInstance reportInstance, SalesforceException ex) {
+                    processResponse(exchange, reportInstance, ex, callback);
+                }
+            });
+    }
+
+    private void processGetReportInstances(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        final String reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+
+        analyticsClient.getReportInstances(reportId, new AnalyticsApiClient.ReportInstanceListResponseCallback() {
+            @Override
+            public void onResponse(List<ReportInstance> reportInstances, SalesforceException ex) {
+                processResponse(exchange, reportInstances, ex, callback);
+            }
+        });
+    }
+
+    private void processGetReportResults(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        final String reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+        final String instanceId = getParameter(INSTANCE_ID, exchange, IGNORE_BODY, NOT_OPTIONAL);
+
+        analyticsClient.getReportResults(reportId, instanceId, new AnalyticsApiClient.ReportResultsResponseCallback() {
+            @Override
+            public void onResponse(AbstractReportResultsBase reportResults, SalesforceException ex) {
+                processResponse(exchange, reportResults, ex, callback);
+            }
+        });
+    }
+
+    private void processResponse(Exchange exchange, Object body, SalesforceException ex, AsyncCallback callback) {
+        final Message out = exchange.getOut();
+        if (ex != null) {
+            exchange.setException(ex);
+        } else {
+            out.setBody(body);
+        }
+
+        // copy headers and attachments
+        out.getHeaders().putAll(exchange.getIn().getHeaders());
+        out.getAttachments().putAll(exchange.getIn().getAttachments());
+
+        // signal exchange completion
+        callback.done(false);
+    }
+
+    @Override
+    public void start() throws Exception {
+        ServiceHelper.startService(analyticsClient);
+    }
+
+    @Override
+    public void stop() throws Exception {
+        // stop the client
+        ServiceHelper.stopService(analyticsClient);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
index 80d382d..f83ad9d 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
@@ -51,7 +51,7 @@ public class BulkApiProcessor extends AbstractSalesforceProcessor {
         super(endpoint);
 
         this.bulkClient = new DefaultBulkApiClient(
-                endpointConfigMap.get(SalesforceEndpointConfig.API_VERSION), session, httpClient);
+            (String) endpointConfigMap.get(SalesforceEndpointConfig.API_VERSION), session, httpClient);
     }
 
     @Override
@@ -97,24 +97,24 @@ public class BulkApiProcessor extends AbstractSalesforceProcessor {
                 processGetQueryResult(exchange, callback);
                 break;
             default:
-                throw new SalesforceException("Unknow operation name: " + operationName, null);
+                throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
             }
         } catch (SalesforceException e) {
             exchange.setException(new SalesforceException(
                     String.format("Error processing %s: [%s] \"%s\"",
-                            operationName, e.getStatusCode(), e.getMessage()), e));
+                            operationName.value(), e.getStatusCode(), e.getMessage()), e));
             callback.done(true);
             done = true;
         } catch (InvalidPayloadException e) {
             exchange.setException(new SalesforceException(
                     String.format("Unexpected Error processing %s: \"%s\"",
-                            operationName, e.getMessage()), e));
+                            operationName.value(), e.getMessage()), e));
             callback.done(true);
             done = true;
         } catch (RuntimeException e) {
             exchange.setException(new SalesforceException(
                     String.format("Unexpected Error processing %s: \"%s\"",
-                            operationName, e.getMessage()), e));
+                            operationName.value(), e.getMessage()), e));
             callback.done(true);
             done = true;
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter b/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
new file mode 100644
index 0000000..4488642
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.camel.component.salesforce.api.SalesforceReportResultsToListConverter


[5/8] camel git commit: CAMEL-8900: Fixed Javadoc parser missing first void method in API Component Framework

Posted by dh...@apache.org.
CAMEL-8900: Fixed Javadoc parser missing first void method in API Component Framework


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ef5614d1
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ef5614d1
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ef5614d1

Branch: refs/heads/camel-2.14.x
Commit: ef5614d1ec50e00f97b89fdd20ec1f3881b7a388
Parents: dc370b5
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Wed Jun 24 16:16:13 2015 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Wed Jun 24 20:35:35 2015 -0700

----------------------------------------------------------------------
 .../src/main/java/org/apache/camel/maven/JavadocParser.java    | 5 +++--
 .../test/java/org/apache/camel/maven/JavadocParserTest.java    | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/ef5614d1/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
index 706e0b5..b6a1ea2 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/JavadocParser.java
@@ -86,7 +86,6 @@ public class JavadocParser extends Parser {
 
                             final String hrefAttr = (String) attributes.getAttribute(HTML.Attribute.HREF);
                             if (hrefAttr != null && hrefAttr.contains(hrefPattern)) {
-
                                 // unescape HTML
                                 String methodSignature = hrefAttr.substring(hrefAttr.indexOf('#') + 1);
                                 final int firstHyphen = methodSignature.indexOf('-');
@@ -146,7 +145,9 @@ public class JavadocParser extends Parser {
             }
 
             parserState = ParserState.METHOD_SUMMARY;
-        } else if (parserState == ParserState.METHOD_SUMMARY && HTML.Tag.TABLE.equals(tag.getHTMLTag())) {
+        } else if (parserState == ParserState.METHOD_SUMMARY
+            && !methods.isEmpty()
+            && HTML.Tag.TABLE.equals(tag.getHTMLTag())) {
             // end of method summary table
             parserState = ParserState.INIT;
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/ef5614d1/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java b/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
index 183ffbb..8ee9e1e 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/test/java/org/apache/camel/maven/JavadocParserTest.java
@@ -40,16 +40,16 @@ public class JavadocParserTest extends Assert {
 
         htmlParser.parse(new InputStreamReader(new URL(JAVA6_STRING).openStream(), "UTF-8"));
         assertNull("Java6 getErrorMessage", htmlParser.getErrorMessage());
-        assertFalse("Java6 getMethods", htmlParser.getMethods().isEmpty());
+        assertEquals("Java6 getMethods", 65, htmlParser.getMethods().size());
         htmlParser.reset();
 
         htmlParser.parse(new InputStreamReader(new URL(JAVA7_STRING).openStream(), "UTF-8"));
         assertNull("Java7 getErrorMessage", htmlParser.getErrorMessage());
-        assertFalse("Java7 getMethods", htmlParser.getMethods().isEmpty());
+        assertEquals("Java7 getMethods", 65, htmlParser.getMethods().size());
         htmlParser.reset();
 
         htmlParser.parse(new InputStreamReader(new URL(JAVA8_STRING).openStream(), "UTF-8"));
         assertNull("Java8 getErrorMessage", htmlParser.getErrorMessage());
-        assertFalse("Java8 getMethods", htmlParser.getMethods().isEmpty());
+        assertEquals("Java8 getMethods", 67, htmlParser.getMethods().size());
     }
 }


[4/8] camel git commit: CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API

Posted by dh...@apache.org.
CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/7e3b3510
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/7e3b3510
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/7e3b3510

Branch: refs/heads/camel-2.15.x
Commit: 7e3b3510130d0f26838e79f90a1d77610619de76
Parents: 59ae68d
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Wed Jun 24 18:14:02 2015 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Wed Jun 24 20:35:12 2015 -0700

----------------------------------------------------------------------
 .../camel-salesforce-component/pom.xml          |   5 +
 .../salesforce/SalesforceEndpointConfig.java    |  59 ++-
 .../salesforce/SalesforceProducer.java          |  20 +-
 .../SalesforceReportResultsToListConverter.java | 515 +++++++++++++++++++
 .../salesforce/api/dto/PickListValue.java       |   2 +-
 .../salesforce/api/dto/RestResources.java       |   9 +
 .../salesforce/api/dto/SObjectField.java        |   9 +
 .../reports/AbstractAttributesBase.java         |  53 ++
 .../reports/AbstractReportResultsBase.java      |  91 ++++
 .../analytics/reports/AggregateColumnInfo.java  |  42 ++
 .../dto/analytics/reports/AsyncAttributes.java  |  71 +++
 .../analytics/reports/AsyncReportResults.java   |  33 ++
 .../analytics/reports/ColumnSortOrderEnum.java  |  24 +
 .../analytics/reports/DateGranularityEnum.java  |  73 +++
 .../dto/analytics/reports/DetailColumnInfo.java |  44 ++
 .../dto/analytics/reports/FilterOperator.java   |  44 ++
 .../api/dto/analytics/reports/FilterValue.java  |  44 ++
 .../api/dto/analytics/reports/FormatEnum.java   |  57 ++
 .../analytics/reports/GroupingColumnInfo.java   |  33 ++
 .../api/dto/analytics/reports/GroupingInfo.java |  62 +++
 .../dto/analytics/reports/GroupingValue.java    |  72 +++
 .../api/dto/analytics/reports/Groupings.java    |  35 ++
 .../analytics/reports/QueryRecordsReport.java   |  40 ++
 .../api/dto/analytics/reports/RecentReport.java |  71 +++
 .../api/dto/analytics/reports/Report.java       | 100 ++++
 .../analytics/reports/ReportDescription.java    |  53 ++
 .../reports/ReportExtendedMetadata.java         |  55 ++
 .../reports/ReportFactWithDetails.java          |  44 ++
 .../api/dto/analytics/reports/ReportFilter.java |  53 ++
 .../dto/analytics/reports/ReportFormatEnum.java |  24 +
 .../dto/analytics/reports/ReportInstance.java   |  90 ++++
 .../dto/analytics/reports/ReportMetadata.java   | 143 +++++
 .../api/dto/analytics/reports/ReportRow.java    |  35 ++
 .../dto/analytics/reports/ReportStatusEnum.java |  24 +
 .../api/dto/analytics/reports/ReportType.java   |  44 ++
 .../dto/analytics/reports/ReportTypeColumn.java |  62 +++
 .../reports/ReportTypeColumnCategory.java       |  46 ++
 .../analytics/reports/ReportTypeMetadata.java   |  47 ++
 .../api/dto/analytics/reports/SummaryValue.java |  58 +++
 .../dto/analytics/reports/SyncAttributes.java   |  43 ++
 .../analytics/reports/SyncReportResults.java    |  34 ++
 .../salesforce/internal/OperationName.java      |  10 +-
 .../internal/client/AnalyticsApiClient.java     |  71 +++
 .../client/DefaultAnalyticsApiClient.java       | 339 ++++++++++++
 .../processor/AbstractRestProcessor.java        |  10 +-
 .../processor/AbstractSalesforceProcessor.java  |  65 ++-
 .../processor/AnalyticsApiProcessor.java        | 227 ++++++++
 .../internal/processor/BulkApiProcessor.java    |  10 +-
 .../services/org/apache/camel/TypeConverter     |  18 +
 .../salesforce/AnalyticsApiIntegrationTest.java | 285 ++++++++++
 .../component/salesforce/LoginConfigHelper.java |   2 +-
 51 files changed, 3473 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/pom.xml b/components/camel-salesforce/camel-salesforce-component/pom.xml
index a1291f1..bd01a68 100644
--- a/components/camel-salesforce/camel-salesforce-component/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-component/pom.xml
@@ -115,6 +115,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-csv</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-server</artifactId>
       <version>${jetty-version}</version>

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
index 39b860a..f8f7e9b 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
 import org.apache.camel.component.salesforce.api.dto.bulk.ContentType;
 import org.apache.camel.component.salesforce.internal.PayloadFormat;
 import org.apache.camel.component.salesforce.internal.dto.NotifyForFieldsEnum;
@@ -63,6 +64,12 @@ public class SalesforceEndpointConfig implements Cloneable {
     public static final String JOB_ID = "jobId";
     public static final String BATCH_ID = "batchId";
     public static final String RESULT_ID = "resultId";
+    
+    // parameters for Analytics API
+    public static final String REPORT_ID = "reportId";
+    public static final String INCLUDE_DETAILS = "includeDetails";
+    public static final String REPORT_METADATA = "reportMetadata";
+    public static final String INSTANCE_ID = "instanceId";
 
     // general properties
     @UriParam
@@ -121,6 +128,16 @@ public class SalesforceEndpointConfig implements Cloneable {
     private Boolean notifyForOperationDelete;
     @UriParam
     private Boolean notifyForOperationUndelete;
+    
+    // Analytics API properties
+    @UriParam
+    private String reportId;
+    @UriParam
+    private Boolean includeDetails;
+    @UriParam
+    private ReportMetadata reportMetadata;
+    @UriParam
+    private String instanceId;
 
     // Jetty HttpClient, set using reference
     @UriParam
@@ -336,6 +353,38 @@ public class SalesforceEndpointConfig implements Cloneable {
         this.notifyForOperationUndelete = notifyForOperationUndelete;
     }
 
+    public String getReportId() {
+        return reportId;
+    }
+
+    public void setReportId(String reportId) {
+        this.reportId = reportId;
+    }
+
+    public Boolean getIncludeDetails() {
+        return includeDetails;
+    }
+
+    public void setIncludeDetails(Boolean includeDetails) {
+        this.includeDetails = includeDetails;
+    }
+
+    public ReportMetadata getReportMetadata() {
+        return reportMetadata;
+    }
+
+    public void setReportMetadata(ReportMetadata reportMetadata) {
+        this.reportMetadata = reportMetadata;
+    }
+
+    public String getInstanceId() {
+        return instanceId;
+    }
+
+    public void setInstanceId(String instanceId) {
+        this.instanceId = instanceId;
+    }
+
     public void setHttpClient(HttpClient httpClient) {
         this.httpClient = httpClient;
     }
@@ -344,9 +393,9 @@ public class SalesforceEndpointConfig implements Cloneable {
         return httpClient;
     }
 
-    public Map<String, String> toValueMap() {
+    public Map<String, Object> toValueMap() {
 
-        final Map<String, String> valueMap = new HashMap<String, String>();
+        final Map<String, Object> valueMap = new HashMap<String, Object>();
         valueMap.put(FORMAT, format.toString().toLowerCase());
         valueMap.put(API_VERSION, apiVersion);
 
@@ -370,6 +419,12 @@ public class SalesforceEndpointConfig implements Cloneable {
         valueMap.put(JOB_ID, jobId);
         valueMap.put(BATCH_ID, batchId);
         valueMap.put(RESULT_ID, resultId);
+        
+        // add analytics API properties
+        valueMap.put(REPORT_ID, reportId);
+        valueMap.put(INCLUDE_DETAILS, includeDetails);
+        valueMap.put(REPORT_METADATA, reportMetadata);
+        valueMap.put(INSTANCE_ID, instanceId);
 
         return Collections.unmodifiableMap(valueMap);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
index 42c1bfe..55b1bf0 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
@@ -21,6 +21,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.component.salesforce.api.SalesforceException;
 import org.apache.camel.component.salesforce.internal.OperationName;
 import org.apache.camel.component.salesforce.internal.PayloadFormat;
+import org.apache.camel.component.salesforce.internal.processor.AnalyticsApiProcessor;
 import org.apache.camel.component.salesforce.internal.processor.BulkApiProcessor;
 import org.apache.camel.component.salesforce.internal.processor.JsonRestProcessor;
 import org.apache.camel.component.salesforce.internal.processor.SalesforceProcessor;
@@ -42,8 +43,11 @@ public class SalesforceProducer extends DefaultAsyncProducer {
         final PayloadFormat payloadFormat = endpointConfig.getFormat();
 
         // check if its a Bulk Operation
-        if (isBulkOperation(endpoint.getOperationName())) {
+        final OperationName operationName = endpoint.getOperationName();
+        if (isBulkOperation(operationName)) {
             processor = new BulkApiProcessor(endpoint);
+        } else if (isAnalyticsOperation(operationName)) {
+            processor = new AnalyticsApiProcessor(endpoint);
         } else {
             // create an appropriate processor
             if (payloadFormat == PayloadFormat.JSON) {
@@ -75,6 +79,20 @@ public class SalesforceProducer extends DefaultAsyncProducer {
         }
     }
 
+    private boolean isAnalyticsOperation(OperationName operationName) {
+        switch (operationName) {
+        case GET_RECENT_REPORTS:
+        case GET_REPORT_DESCRIPTION:
+        case EXECUTE_SYNCREPORT:
+        case EXECUTE_ASYNCREPORT:
+        case GET_REPORT_INSTANCES:
+        case GET_REPORT_RESULTS:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         log.debug("Processing {}",

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java
new file mode 100644
index 0000000..3cacf39
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java
@@ -0,0 +1,515 @@
+/**
+ * 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.salesforce.api;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AbstractReportResultsBase;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AggregateColumnInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AsyncReportResults;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.DetailColumnInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.GroupingColumnInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.GroupingInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.GroupingValue;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportExtendedMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportFactWithDetails;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportRow;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportStatusEnum;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.SummaryValue;
+
+/**
+ * Salesforce report results to <code>List&lt;List&lt;String&gt;&gt;</code>converter.
+ */
+@Converter
+public final class SalesforceReportResultsToListConverter {
+
+    public static final String INCLUDE_DETAILS = "CamelSalesforceIncludeDetails";
+    public static final String INCLUDE_HEADERS = "CamelSalesforceIncludeHeaders";
+    public static final String INCLUDE_SUMMARY = "CamelSalesforceIncludeSummary";
+
+    private static final String ROW_COUNT = "RowCount";
+    private static final String EMPTY_VALUE = "";
+    private static final List<String> EMPTY_STRING_LIST = Collections.emptyList();
+
+    private SalesforceReportResultsToListConverter() {
+    }
+
+    @Converter
+    public static List<List<String>> convertToList(final AbstractReportResultsBase reportResults,
+                                                   final Exchange exchange) {
+
+        List<List<String>> results = null;
+        if (reportResults instanceof AsyncReportResults) {
+            AsyncReportResults asyncReportResults = (AsyncReportResults) reportResults;
+            final ReportStatusEnum status = asyncReportResults.getAttributes().getStatus();
+            // only successfully completed async report results have data rows
+            if (status != ReportStatusEnum.Success) {
+                throw new IllegalArgumentException("Invalid asynchronous report results status " + status);
+            }
+        }
+
+        switch (reportResults.getReportMetadata().getReportFormat()) {
+        case TABULAR:
+            results = convertTabularResults(reportResults, exchange);
+            break;
+        case SUMMARY:
+            results = convertSummaryResults(reportResults, exchange);
+            break;
+        case MATRIX:
+            results = convertMatrixResults(reportResults, exchange);
+            break;
+        default:
+            // ignore
+        }
+
+        return results;
+    }
+
+    private static List<List<String>> convertTabularResults(final AbstractReportResultsBase reportResults, final Exchange exchange) {
+
+        final ArrayList<List<String>> result = new ArrayList<List<String>>();
+
+        final ReportMetadata reportMetadata = reportResults.getReportMetadata();
+        final String[] detailColumns = reportMetadata.getDetailColumns();
+
+        final ReportExtendedMetadata reportExtendedMetadata = reportResults.getReportExtendedMetadata();
+        final ReportFactWithDetails factWithDetails = reportResults.getFactMap().get("T!T");
+
+        // include detail rows?
+        final String[] aggregates = reportMetadata.getAggregates();
+        if (reportResults.getHasDetailRows() && getOption(exchange, INCLUDE_DETAILS, Boolean.TRUE)) {
+
+            final int rowLength = detailColumns.length;
+
+            // include detail headers?
+            if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+
+                final List<String> headers = new ArrayList<String>(rowLength);
+                result.add(headers);
+
+                addColumnHeaders(headers, reportExtendedMetadata.getDetailColumnInfo(), detailColumns);
+            }
+
+            final ReportRow[] reportRows = factWithDetails.getRows();
+            result.ensureCapacity(result.size() + reportRows.length);
+            for (ReportRow reportRow : reportRows) {
+
+                final List<String> row = new ArrayList<String>(rowLength);
+                result.add(row);
+
+                addRowValues(row, reportRow.getDataCells());
+            }
+
+            // include summary values?
+            if (aggregates.length > 0 && getOption(exchange, INCLUDE_SUMMARY, Boolean.TRUE)) {
+
+                addSummaryRows(result, detailColumns, null, aggregates, factWithDetails.getAggregates());
+            }
+
+        } else if (aggregates.length > 0) {
+
+            final int rowLength = aggregates.length;
+
+            // include summary headers?
+            if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+
+                final List<String> headers = new ArrayList<String>(rowLength);
+                result.add(headers);
+
+                addColumnHeaders(headers, reportExtendedMetadata.getAggregateColumnInfo(), aggregates);
+            }
+
+            // add summary values
+            final List<String> row = new ArrayList<String>(rowLength);
+            result.add(row);
+            addRowValues(row, factWithDetails.getAggregates());
+        }
+
+        return result;
+    }
+
+    private static List<List<String>> convertSummaryResults(final AbstractReportResultsBase reportResults, Exchange exchange) {
+
+        final ArrayList<List<String>> result = new ArrayList<List<String>>();
+
+        final ReportMetadata reportMetadata = reportResults.getReportMetadata();
+        final ReportExtendedMetadata reportExtendedMetadata = reportResults.getReportExtendedMetadata();
+        final String[] aggregates = reportMetadata.getAggregates();
+
+        final boolean includeDetails = reportResults.getHasDetailRows()
+            && getOption(exchange, INCLUDE_DETAILS, Boolean.TRUE);
+        final boolean includeSummary = aggregates.length > 0 && getOption(exchange, INCLUDE_SUMMARY, Boolean.TRUE);
+
+        // column list, including grouping columns and details if required
+        final ArrayList<DetailColumnInfo> columnInfos = new ArrayList<DetailColumnInfo>();
+        final String[] columnNames = getResultColumns(columnInfos, reportMetadata, reportExtendedMetadata,
+            includeDetails, includeSummary);
+
+        // include detail headers?
+        if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+            addColumnHeaders(result, columnInfos);
+        }
+
+        // process down groups
+        for (GroupingValue groupingValue : reportResults.getGroupingsDown().getGroupings()) {
+            addSummaryGroupValues(result, reportResults, columnNames, groupingValue,
+                EMPTY_STRING_LIST, includeDetails, includeSummary);
+        }
+
+        // add grand total
+        if (includeSummary) {
+
+            final ReportFactWithDetails grandTotal = reportResults.getFactMap().get("T!T");
+
+            addSummaryValues(result, includeDetails, columnNames, EMPTY_STRING_LIST,
+                aggregates, grandTotal.getAggregates());
+        }
+
+        return result;
+    }
+
+    private static List<List<String>> convertMatrixResults(final AbstractReportResultsBase reportResults, Exchange exchange) {
+        final ArrayList<List<String>> result = new ArrayList<List<String>>();
+
+        final ReportMetadata reportMetadata = reportResults.getReportMetadata();
+        final ReportExtendedMetadata reportExtendedMetadata = reportResults.getReportExtendedMetadata();
+        final String[] aggregates = reportMetadata.getAggregates();
+
+        final boolean includeDetails = reportResults.getHasDetailRows()
+            && getOption(exchange, INCLUDE_DETAILS, Boolean.TRUE);
+        final boolean includeSummary = aggregates.length > 0 && getOption(exchange, INCLUDE_SUMMARY, Boolean.TRUE);
+
+        // column list, including grouping columns and details if required
+        final ArrayList<DetailColumnInfo> columnInfos = new ArrayList<DetailColumnInfo>();
+        final String[] columnNames = getResultColumns(columnInfos, reportMetadata, reportExtendedMetadata,
+            includeDetails, includeSummary);
+
+        // include detail headers?
+        if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+            addColumnHeaders(result, columnInfos);
+        }
+
+        // process down groups
+        final GroupingValue[] groupingsDown = reportResults.getGroupingsDown().getGroupings();
+        for (GroupingValue groupingValue : groupingsDown) {
+            addMatrixGroupValues(result, reportResults, columnNames, groupingValue,
+                EMPTY_STRING_LIST, includeDetails, includeSummary, EMPTY_VALUE, true);
+        }
+
+        // add grand total
+        if (includeSummary) {
+
+            final Map<String, ReportFactWithDetails> factMap = reportResults.getFactMap();
+
+            // first add summary for across groups
+            final List<String> downGroupsPrefix = new ArrayList<String>(
+                Collections.nCopies(groupingsDown.length, EMPTY_VALUE));
+
+            for (GroupingValue acrossGrouping : reportResults.getGroupingsAcross().getGroupings()) {
+                addAcrossGroupSummaryValues(result, reportMetadata,
+                    includeDetails, columnNames, factMap, downGroupsPrefix, acrossGrouping);
+            }
+
+            final ReportFactWithDetails grandTotal = factMap.get("T!T");
+            addSummaryValues(result, includeDetails, columnNames, EMPTY_STRING_LIST,
+                reportResults.getReportMetadata().getAggregates(), grandTotal.getAggregates());
+        }
+
+        return result;
+    }
+
+    private static void addAcrossGroupSummaryValues(ArrayList<List<String>> result, ReportMetadata reportMetadata,
+                                                    boolean includeDetails, String[] columnNames,
+                                                    Map<String, ReportFactWithDetails> factMap,
+                                                    List<String> downGroupsPrefix, GroupingValue acrossGrouping) {
+
+        final List<String> newDownGroupsPrefix = new ArrayList<String>(downGroupsPrefix);
+        newDownGroupsPrefix.add(acrossGrouping.getLabel());
+
+        addSummaryValues(result, includeDetails, columnNames, newDownGroupsPrefix,
+            reportMetadata.getAggregates(),
+            factMap.get("T!" + acrossGrouping.getKey()).getAggregates());
+
+        // process across subgroups
+        for (GroupingValue subGroup : acrossGrouping.getGroupings()) {
+            addAcrossGroupSummaryValues(result, reportMetadata, includeDetails, columnNames, factMap,
+                newDownGroupsPrefix, subGroup);
+        }
+    }
+
+    private static void addMatrixGroupValues(ArrayList<List<String>> result, AbstractReportResultsBase reportResults,
+                                             String[] columnNames, GroupingValue groupingValue,
+                                             List<String> rowPrefix, boolean includeDetails, boolean includeSummary,
+                                             String keyPrefix, boolean downGroup) {
+
+        final String groupKey = groupingValue.getKey();
+        final String newKeyPrefix = keyPrefix + groupKey;
+
+        // group values prefix
+        final List<String> newPrefix = new ArrayList<String>(rowPrefix);
+        newPrefix.add(groupingValue.getLabel());
+
+        final GroupingValue[] groupings = groupingValue.getGroupings();
+        // has subgroups?
+        if (groupings.length > 0) {
+
+            for (GroupingValue subGroup : groupings) {
+                addMatrixGroupValues(result, reportResults, columnNames, subGroup, newPrefix,
+                    includeDetails, includeSummary, newKeyPrefix + "_", downGroup);
+            }
+
+        // process across groupings?
+        } else if (downGroup) {
+
+            for (GroupingValue acrossGroup : reportResults.getGroupingsAcross().getGroupings()) {
+                addMatrixGroupValues(result, reportResults, columnNames, acrossGroup, newPrefix,
+                    includeDetails, includeSummary, newKeyPrefix + "!", false);
+            }
+
+        // add lowest level across group detail rows?
+        } else if (includeDetails) {
+
+            addDetailRows(result, newPrefix, reportResults.getFactMap().get(newKeyPrefix));
+
+        // add group columns only at lowest across level?
+        } else if (!includeSummary) {
+
+            result.add(newPrefix);
+
+        }
+
+        // add summary values for down group or lowest level across group
+        if (includeSummary) {
+
+            final String summaryKey = getGroupTotalKey(keyPrefix, downGroup, groupKey);
+
+            addSummaryValues(result, includeDetails, columnNames, newPrefix,
+                reportResults.getReportMetadata().getAggregates(),
+                reportResults.getFactMap().get(summaryKey).getAggregates());
+        }
+    }
+
+    private static String getGroupTotalKey(String keyPrefix, boolean downGroup, String key) {
+        if (downGroup) {
+            // keyPrefix has rows only
+            return keyPrefix + key + "!T";
+        } else {
+            // keyPrefix is of the form r(_r)*!(c_)*
+            return keyPrefix + key;
+        }
+    }
+
+    private static void addSummaryGroupValues(ArrayList<List<String>> result, AbstractReportResultsBase reportResults,
+                                              String[] columnNames, GroupingValue groupingValue,
+                                              List<String> rowPrefix, boolean includeDetails, boolean includeSummary) {
+
+        // get fact map at this level
+        final ReportFactWithDetails factWithDetails = reportResults.getFactMap().get(groupingValue.getKey() + "!T");
+
+        final List<String> newPrefix = new ArrayList<String>(rowPrefix);
+        newPrefix.add(groupingValue.getLabel());
+
+        // more groups?
+        final GroupingValue[] groupings = groupingValue.getGroupings();
+        if (groupings.length > 0) {
+
+            for (GroupingValue subGroup : groupings) {
+                addSummaryGroupValues(result, reportResults, columnNames, subGroup, newPrefix,
+                    includeDetails, includeSummary);
+            }
+
+        // add lowest level group detail rows?
+        } else if (includeDetails) {
+
+            addDetailRows(result, newPrefix, factWithDetails);
+
+            // add group columns only at lowest level?
+        } else if (!includeSummary) {
+            result.add(newPrefix);
+        }
+
+        if (includeSummary) {
+            final SummaryValue[] summaryValues = factWithDetails.getAggregates();
+            final String[] aggregates = reportResults.getReportMetadata().getAggregates();
+
+            addSummaryValues(result, includeDetails, columnNames, newPrefix, aggregates, summaryValues);
+        }
+    }
+
+    private static void addDetailRows(ArrayList<List<String>> result, List<String> newPrefix, ReportFactWithDetails factWithDetails) {
+        final ReportRow[] rows = factWithDetails.getRows();
+        result.ensureCapacity(result.size() + rows.length);
+        for (ReportRow row : rows) {
+            final ArrayList<String> rowValues = new ArrayList<String>(newPrefix);
+            addRowValues(rowValues, row.getDataCells());
+            result.add(rowValues);
+        }
+    }
+
+    private static void addSummaryValues(ArrayList<List<String>> result, boolean includeDetails,
+                                         String[] columnNames, List<String> newPrefix,
+                                         String[] aggregates, SummaryValue[] summaryValues) {
+        // no summary values to add
+        if (summaryValues.length == 0) {
+            return;
+        }
+
+        if (includeDetails) {
+            // add summary rows for this group
+            addSummaryRows(result, columnNames, newPrefix,
+                aggregates, summaryValues);
+        } else {
+            // add summary values as columns for this group
+            final ArrayList<String> summaryRow = new ArrayList<String>(newPrefix);
+            // add remaining group values
+            final int nGroups = columnNames.length - summaryValues.length;
+            for (int i = summaryRow.size(); i < nGroups; i++) {
+                summaryRow.add(EMPTY_VALUE);
+            }
+            addRowValues(summaryRow, summaryValues);
+            result.add(summaryRow);
+        }
+    }
+
+    private static void addSummaryRows(List<List<String>> result,
+                                       String[] detailColumns, List<String> rowPrefix,
+                                       String[] aggregateColumns, SummaryValue[] summaryValues) {
+
+        final ArrayList<List<String>> rows = new ArrayList<List<String>>(summaryValues.length + 1);
+        String rowCount = null;
+        for (int i = 0; i < aggregateColumns.length; i++) {
+
+            final String aggregate = aggregateColumns[i];
+
+            final String valueLabel = summaryValues[i].getLabel();
+            if (ROW_COUNT.equals(aggregate)) {
+                rowCount = valueLabel;
+            } else {
+
+                final List<String> summaryRow = rowPrefix == null
+                    ? new ArrayList<String>() : new ArrayList<String>(rowPrefix);
+                rows.add(summaryRow);
+
+                // skip rowPrefix columns if not null
+                for (int j = rowPrefix == null ? 0 : rowPrefix.size(); j < detailColumns.length; j++) {
+
+                    final String columnName = detailColumns[j];
+                    if (aggregate.endsWith("!" + columnName)) {
+                        final StringBuilder valueBuilder = new StringBuilder();
+                        if (aggregate.startsWith("a!")) {
+                            valueBuilder.append("avg ");
+                        } else if (aggregate.startsWith("mx!")) {
+                            valueBuilder.append("max ");
+                        } else if (aggregate.startsWith("m!")) {
+                            valueBuilder.append("min ");
+                        }
+                        valueBuilder.append(valueLabel);
+                        summaryRow.add(valueBuilder.toString());
+                    } else {
+                        summaryRow.add(EMPTY_VALUE);
+                    }
+                }
+            }
+        }
+
+        // add a Grand Totals separator row
+        final List<String> grandTotal = new ArrayList<String>();
+        result.add(grandTotal);
+
+        if (rowCount != null) {
+            grandTotal.add("Grand Totals (" +  rowCount + " records)");
+        } else {
+            grandTotal.add("Grand Totals");
+        }
+
+        // add summary values rows
+        result.addAll(rows);
+    }
+
+    private static String[] getResultColumns(List<DetailColumnInfo> result, ReportMetadata reportMetadata,
+                                                       ReportExtendedMetadata reportExtendedMetadata,
+                                                       boolean includeDetails, boolean includeSummary) {
+
+        final List<String> columnNames = new ArrayList<String>();
+
+        // add grouping columns before detail columns
+        final Map<String, GroupingColumnInfo> groupingColumnInfos = reportExtendedMetadata.getGroupingColumnInfo();
+        for (GroupingInfo downGroup : reportMetadata.getGroupingsDown()) {
+            final String name = downGroup.getName();
+            columnNames.add(name);
+            result.add(groupingColumnInfos.get(name));
+        }
+        for (GroupingInfo acrossGroup : reportMetadata.getGroupingsAcross()) {
+            final String name = acrossGroup.getName();
+            columnNames.add(name);
+            result.add(groupingColumnInfos.get(name));
+        }
+
+        // include details?
+        if (!includeDetails) {
+            // include summary columns?
+            if (includeSummary) {
+                final Map<String, AggregateColumnInfo> aggregateColumnInfos =
+                    reportExtendedMetadata.getAggregateColumnInfo();
+                for (String aggregateColumnName : reportMetadata.getAggregates()) {
+                    columnNames.add(aggregateColumnName);
+                    result.add(aggregateColumnInfos.get(aggregateColumnName));
+                }
+            }
+        } else {
+            // add detail columns
+            final Map<String, DetailColumnInfo> detailColumnInfo = reportExtendedMetadata.getDetailColumnInfo();
+            for (String columnName : reportMetadata.getDetailColumns()) {
+                columnNames.add(columnName);
+                result.add(detailColumnInfo.get(columnName));
+            }
+        }
+
+        return columnNames.toArray(new String[columnNames.size()]);
+    }
+
+    private static void addColumnHeaders(List<String> headers,
+                                         Map<String, ? extends DetailColumnInfo> columnInfos, String[] columns) {
+        for (String columnName : columns) {
+            headers.add(columnInfos.get(columnName).getLabel());
+        }
+    }
+
+    private static void addColumnHeaders(List<List<String>> result, ArrayList<DetailColumnInfo> columnInfos) {
+        final ArrayList<String> headers = new ArrayList<String>(columnInfos.size());
+        for (DetailColumnInfo info : columnInfos) {
+            headers.add(info.getLabel());
+        }
+        result.add(headers);
+    }
+
+    private static void addRowValues(List<String> row, SummaryValue[] values) {
+        for (SummaryValue summaryValue : values) {
+            row.add(summaryValue.getLabel());
+        }
+    }
+
+    private static boolean getOption(Exchange exchange, String name, Boolean defaultValue) {
+        return exchange.getIn().getHeader(name, defaultValue, Boolean.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
index 2ae2cfd..4e69738 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
@@ -19,7 +19,7 @@ package org.apache.camel.component.salesforce.api.dto;
 /**
  * Salesforce DTO for picklist value.
  */
-public class PickListValue {
+public class PickListValue extends AbstractDTOBase {
 
     private String value;
     private String label;

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
index b37aa13..a07cb6a 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
@@ -45,6 +45,7 @@ public class RestResources extends AbstractDTOBase {
     private String compactLayouts;
     private String actions;
     private String tabs;
+    private String wave;
 
     public String getSobjects() {
         return sobjects;
@@ -213,4 +214,12 @@ public class RestResources extends AbstractDTOBase {
     public void setTabs(String tabs) {
         this.tabs = tabs;
     }
+
+    public String getWave() {
+        return wave;
+    }
+
+    public void setWave(String wave) {
+        this.wave = wave;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
index 312e6c3..967064f 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
@@ -74,6 +74,7 @@ public class SObjectField extends AbstractDTOBase {
     private String maskType;
     private Boolean queryByDistance;
     private String referenceTargetField;
+    private Boolean encrypted;
 
     public Integer getLength() {
         return length;
@@ -474,4 +475,12 @@ public class SObjectField extends AbstractDTOBase {
     public void setReferenceTargetField(String referenceTargetField) {
         this.referenceTargetField = referenceTargetField;
     }
+
+    public Boolean getEncrypted() {
+        return encrypted;
+    }
+
+    public void setEncrypted(Boolean encrypted) {
+        this.encrypted = encrypted;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java
new file mode 100644
index 0000000..90de38b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java
@@ -0,0 +1,53 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Base DTO for report attributes.
+ */
+public abstract class AbstractAttributesBase extends AbstractDTOBase {
+
+    private String type;
+    private String reportName;
+    private String reportId;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getReportName() {
+        return reportName;
+    }
+
+    public void setReportName(String reportName) {
+        this.reportName = reportName;
+    }
+
+    public String getReportId() {
+        return reportId;
+    }
+
+    public void setReportId(String reportId) {
+        this.reportId = reportId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java
new file mode 100644
index 0000000..8d0f475
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java
@@ -0,0 +1,91 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Base DTO for report results.
+ */
+public abstract class AbstractReportResultsBase extends AbstractDTOBase {
+
+    private Boolean hasDetailRows;
+    private ReportMetadata reportMetadata;
+    private ReportExtendedMetadata reportExtendedMetadata;
+    private Groupings groupingsDown;
+    private Groupings groupingsAcross;
+    private Boolean allData;
+    private Map<String, ReportFactWithDetails> factMap;
+
+    public Boolean getHasDetailRows() {
+        return hasDetailRows;
+    }
+
+    public void setHasDetailRows(Boolean hasDetailRows) {
+        this.hasDetailRows = hasDetailRows;
+    }
+
+    public ReportMetadata getReportMetadata() {
+        return reportMetadata;
+    }
+
+    public void setReportMetadata(ReportMetadata reportMetadata) {
+        this.reportMetadata = reportMetadata;
+    }
+
+    public ReportExtendedMetadata getReportExtendedMetadata() {
+        return reportExtendedMetadata;
+    }
+
+    public void setReportExtendedMetadata(ReportExtendedMetadata reportExtendedMetadata) {
+        this.reportExtendedMetadata = reportExtendedMetadata;
+    }
+
+    public Groupings getGroupingsDown() {
+        return groupingsDown;
+    }
+
+    public void setGroupingsDown(Groupings groupingsDown) {
+        this.groupingsDown = groupingsDown;
+    }
+
+    public Groupings getGroupingsAcross() {
+        return groupingsAcross;
+    }
+
+    public void setGroupingsAcross(Groupings groupingsAcross) {
+        this.groupingsAcross = groupingsAcross;
+    }
+
+    public Boolean getAllData() {
+        return allData;
+    }
+
+    public void setAllData(Boolean allData) {
+        this.allData = allData;
+    }
+
+    public Map<String, ReportFactWithDetails> getFactMap() {
+        return factMap;
+    }
+
+    public void setFactMap(Map<String, ReportFactWithDetails> factMap) {
+        this.factMap = factMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.java
new file mode 100644
index 0000000..766ec9e
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.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.component.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report results aggregate column info.
+ */
+public class AggregateColumnInfo extends DetailColumnInfo {
+
+    private String acrossGroupingContext;
+    private String downGroupingContext;
+
+    public String getAcrossGroupingContext() {
+        return acrossGroupingContext;
+    }
+
+    public void setAcrossGroupingContext(String acrossGroupingContext) {
+        this.acrossGroupingContext = acrossGroupingContext;
+    }
+
+    public String getDownGroupingContext() {
+        return downGroupingContext;
+    }
+
+    public void setDownGroupingContext(String downGroupingContext) {
+        this.downGroupingContext = downGroupingContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java
new file mode 100644
index 0000000..d66583a
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java
@@ -0,0 +1,71 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.joda.time.DateTime;
+
+/**
+ * Async report attributes DTO.
+ */
+public class AsyncAttributes extends AbstractAttributesBase {
+
+    private String id;
+    private ReportStatusEnum status;
+    private String ownerId;
+    private DateTime completionDate;
+    private DateTime requestDate;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public ReportStatusEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(ReportStatusEnum status) {
+        this.status = status;
+    }
+
+    public String getOwnerId() {
+        return ownerId;
+    }
+
+    public void setOwnerId(String ownerId) {
+        this.ownerId = ownerId;
+    }
+
+    public DateTime getCompletionDate() {
+        return completionDate;
+    }
+
+    public void setCompletionDate(DateTime completionDate) {
+        this.completionDate = completionDate;
+    }
+
+    public DateTime getRequestDate() {
+        return requestDate;
+    }
+
+    public void setRequestDate(DateTime requestDate) {
+        this.requestDate = requestDate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java
new file mode 100644
index 0000000..e341fe4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java
@@ -0,0 +1,33 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Sync Report results DTO.
+ */
+public class AsyncReportResults extends AbstractReportResultsBase {
+
+    private AsyncAttributes attributes;
+
+    public AsyncAttributes getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(AsyncAttributes attributes) {
+        this.attributes = attributes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java
new file mode 100644
index 0000000..08d9062
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java
@@ -0,0 +1,24 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Grouping column sort order.
+ */
+public enum ColumnSortOrderEnum {
+    Asc, Desc
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java
new file mode 100644
index 0000000..56e8702
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java
@@ -0,0 +1,73 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonValue;
+
+/**
+ * Report results groupings date granularity.
+ */
+public enum DateGranularityEnum {
+
+    // None
+    NONE("None"),
+    // Day
+    DAY("Day"),
+    // Calendar Week
+    CALENDAR_WEEK("Calendar Week"),
+    // Calendar Month
+    CALENDAR_MONTH("Calendar Month"),
+    // Calendar Quarter
+    CALENDAR_QUARTER("Calendar Quarter"),
+    // Calendar Year
+    CALENDAR_YEAR("Calendar Year"),
+    // Calendar Month in Year
+    CALENDAR_MONTH_IN_YEAR("Calendar Month in Year"),
+    // Calendar Day in Month
+    CALENDAR_DAY_IN_MONTH("Calendar Day in Month"),
+    // Fiscal Period
+    FISCAL_PERIOD("Fiscal Period"),
+    // Fiscal Week
+    FISCAL_WEEK("Fiscal Week"),
+    // Fiscal Quarter
+    FISCAL_QUARTER("Fiscal Quarter"),
+    // Fiscal Year
+    FISCAL_YEAR("Fiscal Year");
+
+    private final String value;
+
+    DateGranularityEnum(String value) {
+        this.value = value;
+    }
+
+    @JsonValue
+    public String value() {
+        return value;
+    }
+
+    @JsonCreator
+    public static DateGranularityEnum fromValue(String value) {
+        for (DateGranularityEnum e : DateGranularityEnum.values()) {
+            if (e.value.equals(value)) {
+                return e;
+            }
+        }
+        throw new IllegalArgumentException(value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java
new file mode 100644
index 0000000..8c3b316
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results details column info.
+ */
+public class DetailColumnInfo extends AbstractDTOBase {
+
+    private String label;
+    private String dataType;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java
new file mode 100644
index 0000000..7358662
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type metadata filter operator reference.
+ */
+public class FilterOperator extends AbstractDTOBase {
+
+    private String name;
+    private String label;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java
new file mode 100644
index 0000000..d5298c4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type column filter value.
+ */
+public class FilterValue extends AbstractDTOBase {
+
+    private String label;
+    private String name;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java
new file mode 100644
index 0000000..b9b825b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java
@@ -0,0 +1,57 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonValue;
+
+/**
+ * Salesforce Enumeration DTO for picklist Format
+ */
+public enum FormatEnum {
+
+    // Matrix
+    MATRIX("Matrix"),
+    // MultiBlock
+    MULTIBLOCK("MultiBlock"),
+    // Summary
+    SUMMARY("Summary"),
+    // Tabular
+    TABULAR("Tabular");
+
+    final String value;
+
+    private FormatEnum(String value) {
+        this.value = value;
+    }
+
+    @JsonValue
+    public String value() {
+        return this.value;
+    }
+
+    @JsonCreator
+    public static FormatEnum fromValue(String value) {
+        for (FormatEnum e : FormatEnum.values()) {
+            if (e.value.equals(value)) {
+                return e;
+            }
+        }
+        throw new IllegalArgumentException(value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java
new file mode 100644
index 0000000..21c3142
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java
@@ -0,0 +1,33 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report results grouping column info.
+ */
+public class GroupingColumnInfo extends DetailColumnInfo {
+
+    private Integer groupingLevel;
+
+    public Integer getGroupingLevel() {
+        return groupingLevel;
+    }
+
+    public void setGroupingLevel(Integer groupingLevel) {
+        this.groupingLevel = groupingLevel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java
new file mode 100644
index 0000000..08588bf
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java
@@ -0,0 +1,62 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report metadata grouping info.
+ */
+public class GroupingInfo extends AbstractDTOBase {
+
+    private String name;
+    private String sortAggregate;
+    private ColumnSortOrderEnum sortOrder;
+    private DateGranularityEnum dateGranularity;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSortAggregate() {
+        return sortAggregate;
+    }
+
+    public void setSortAggregate(String sortAggregate) {
+        this.sortAggregate = sortAggregate;
+    }
+
+    public ColumnSortOrderEnum getSortOrder() {
+        return sortOrder;
+    }
+
+    public void setSortOrder(ColumnSortOrderEnum sortOrder) {
+        this.sortOrder = sortOrder;
+    }
+
+    public DateGranularityEnum getDateGranularity() {
+        return dateGranularity;
+    }
+
+    public void setDateGranularity(DateGranularityEnum dateGranularity) {
+        this.dateGranularity = dateGranularity;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java
new file mode 100644
index 0000000..b27e3d4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java
@@ -0,0 +1,72 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results grouping value.
+ */
+public class GroupingValue extends AbstractDTOBase {
+
+    private String value;
+    private String key;
+    private String label;
+    private GroupingValue[] groupings;
+    // TODO the description is vague about this!!!
+    private GroupingValue[] dategroupings;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public GroupingValue[] getGroupings() {
+        return groupings;
+    }
+
+    public void setGroupings(GroupingValue[] groupings) {
+        this.groupings = groupings;
+    }
+
+    public GroupingValue[] getDategroupings() {
+        return dategroupings;
+    }
+
+    public void setDategroupings(GroupingValue[] dategroupings) {
+        this.dategroupings = dategroupings;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java
new file mode 100644
index 0000000..0bb8af1
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java
@@ -0,0 +1,35 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results groupings.
+ */
+public class Groupings extends AbstractDTOBase {
+
+    private GroupingValue[] groupings;
+
+    public GroupingValue[] getGroupings() {
+        return groupings;
+    }
+
+    public void setGroupings(GroupingValue[] groupings) {
+        this.groupings = groupings;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java
new file mode 100644
index 0000000..3e276f1
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java
@@ -0,0 +1,40 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.List;
+
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractQueryRecordsBase;
+
+/**
+ * Salesforce QueryRecords DTO for type Report
+ */
+public class QueryRecordsReport extends AbstractQueryRecordsBase {
+
+    @XStreamImplicit
+    private List<Report> records;
+
+    public List<Report> getRecords() {
+        return records;
+    }
+
+    public void setRecords(List<Report> records) {
+        this.records = records;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java
new file mode 100644
index 0000000..547b0a7
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java
@@ -0,0 +1,71 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report list info DTO.
+ */
+public class RecentReport extends AbstractDTOBase {
+
+    private String name;
+    private String id;
+    private String url;
+    private String describeUrl;
+    private String instancesUrl;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getDescribeUrl() {
+        return describeUrl;
+    }
+
+    public void setDescribeUrl(String describeUrl) {
+        this.describeUrl = describeUrl;
+    }
+
+    public String getInstancesUrl() {
+        return instancesUrl;
+    }
+
+    public void setInstancesUrl(String instancesUrl) {
+        this.instancesUrl = instancesUrl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java
new file mode 100644
index 0000000..452480a
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java
@@ -0,0 +1,100 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamConverter;
+
+import org.apache.camel.component.salesforce.api.PicklistEnumConverter;
+import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Salesforce DTO for SObject Report
+ */
+//CHECKSTYLE:OFF
+@XStreamAlias("Report")
+public class Report extends AbstractSObjectBase {
+
+    // Description
+    private String Description;
+
+    // DeveloperName
+    private String DeveloperName;
+
+    // NamespacePrefix
+    private String NamespacePrefix;
+
+    // LastRunDate
+    private org.joda.time.DateTime LastRunDate;
+
+    // Format
+    @XStreamConverter(PicklistEnumConverter.class)
+    private FormatEnum Format;
+
+    @JsonProperty("Description")
+    public String getDescription() {
+        return this.Description;
+    }
+
+    @JsonProperty("Description")
+    public void setDescription(String Description) {
+        this.Description = Description;
+    }
+
+    @JsonProperty("DeveloperName")
+    public String getDeveloperName() {
+        return this.DeveloperName;
+    }
+
+    @JsonProperty("DeveloperName")
+    public void setDeveloperName(String DeveloperName) {
+        this.DeveloperName = DeveloperName;
+    }
+
+    @JsonProperty("NamespacePrefix")
+    public String getNamespacePrefix() {
+        return this.NamespacePrefix;
+    }
+
+    @JsonProperty("NamespacePrefix")
+    public void setNamespacePrefix(String NamespacePrefix) {
+        this.NamespacePrefix = NamespacePrefix;
+    }
+
+    @JsonProperty("LastRunDate")
+    public org.joda.time.DateTime getLastRunDate() {
+        return this.LastRunDate;
+    }
+
+    @JsonProperty("LastRunDate")
+    public void setLastRunDate(org.joda.time.DateTime LastRunDate) {
+        this.LastRunDate = LastRunDate;
+    }
+
+    @JsonProperty("Format")
+    public FormatEnum getFormat() {
+        return this.Format;
+    }
+
+    @JsonProperty("Format")
+    public void setFormat(FormatEnum Format) {
+        this.Format = Format;
+    }
+
+}
+//CHECKSTYLE:ON

http://git-wip-us.apache.org/repos/asf/camel/blob/7e3b3510/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java
new file mode 100644
index 0000000..a7c7e60
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java
@@ -0,0 +1,53 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report description DTO.
+ */
+public class ReportDescription extends AbstractDTOBase {
+
+    private ReportTypeMetadata reportTypeMetadata;
+    private ReportExtendedMetadata reportExtendedMetadata;
+    private ReportMetadata reportMetadata;
+
+    public ReportTypeMetadata getReportTypeMetadata() {
+        return reportTypeMetadata;
+    }
+
+    public void setReportTypeMetadata(ReportTypeMetadata reportTypeMetadata) {
+        this.reportTypeMetadata = reportTypeMetadata;
+    }
+
+    public ReportExtendedMetadata getReportExtendedMetadata() {
+        return reportExtendedMetadata;
+    }
+
+    public void setReportExtendedMetadata(ReportExtendedMetadata reportExtendedMetadata) {
+        this.reportExtendedMetadata = reportExtendedMetadata;
+    }
+
+    public ReportMetadata getReportMetadata() {
+        return reportMetadata;
+    }
+
+    public void setReportMetadata(ReportMetadata reportMetadata) {
+        this.reportMetadata = reportMetadata;
+    }
+}


[6/8] camel git commit: CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API

Posted by dh...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java
new file mode 100644
index 0000000..8df7b07
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/AnalyticsApiIntegrationTest.java
@@ -0,0 +1,285 @@
+/**
+ * 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.salesforce;
+
+import java.io.FileInputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.salesforce.api.SalesforceReportResultsToListConverter;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AsyncReportResults;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.QueryRecordsReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.Report;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportStatusEnum;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.SyncReportResults;
+import org.apache.camel.dataformat.csv.CsvDataFormat;
+import org.apache.commons.csv.CSVFormat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Integration test for Salesforce analytics API endpoints. 
+ */
+@RunWith(Theories.class)
+public class AnalyticsApiIntegrationTest extends AbstractSalesforceTestBase {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AnalyticsApiIntegrationTest.class);
+    private static final int RETRY_DELAY = 5000;
+    private static final int REPORT_RESULT_RETRIES = 5;
+    private static final String[] REPORT_OPTIONS = new String[]{
+        SalesforceReportResultsToListConverter.INCLUDE_HEADERS,
+        SalesforceReportResultsToListConverter.INCLUDE_DETAILS,
+        SalesforceReportResultsToListConverter.INCLUDE_SUMMARY
+    };
+    private static final int NUM_OPTIONS = REPORT_OPTIONS.length;
+    private static final int[] POWERS = new int[] {4, 2, 1};
+
+    private static String[] testReportNames;
+    private boolean bodyMetadata;
+
+    /**
+     * Get test report developer names as data points.
+     * @return test report developer names in test-salesforce-login.properties
+     * @throws Exception
+     */
+    @DataPoints
+    public static String[] getTestReportDeveloperNames() throws Exception {
+        return testReportNames;
+    }
+
+    @BeforeClass
+    public static void getReportNames() throws Exception {
+        // get test report names
+        Properties testProperties = new Properties();
+        testProperties.load(new FileInputStream(LoginConfigHelper.TEST_LOGIN_PROPERTIES));
+
+        Map<String, String> reports = new TreeMap<String, String>();
+        for (Map.Entry<Object, Object> entry : testProperties.entrySet()) {
+            final String key = entry.getKey().toString();
+            if (key.matches("report.[0-9]+")) {
+                reports.put(key, entry.getValue().toString());
+            }
+        }
+        assertFalse("Missing entries report.[0-9]+=<Report DeveloperName> in "
+            + LoginConfigHelper.TEST_LOGIN_PROPERTIES, reports.isEmpty());
+
+        final Collection<String> reportNames = reports.values();
+        testReportNames = reportNames.toArray(new String[reportNames.size()]);
+    }
+
+    @Test
+    public void testGetRecentReports() throws Exception {
+
+        final List recentReports = template().requestBody("direct:getRecentReports", null, List.class);
+
+        assertNotNull("getRecentReports", recentReports);
+        assertFalse("getRecentReports empty", recentReports.isEmpty());
+        LOG.debug("getRecentReports: {}", recentReports);
+    }
+
+    @Theory
+    public void testReport(String reportName) throws Exception {
+
+        log.info("Testing report {}...", reportName);
+
+        // get Report Id
+        final QueryRecordsReport reports = template().requestBody("direct:queryReport",
+            "SELECT Id FROM Report WHERE DeveloperName='" + reportName + "'", QueryRecordsReport.class);
+
+        assertNotNull("query", reports);
+        final List<Report> reportsRecords = reports.getRecords();
+        assertFalse("Report not found", reportsRecords.isEmpty());
+        final String testReportId = reportsRecords.get(0).getId();
+        assertNotNull(testReportId);
+
+        // 1. getReportDescription
+        final ReportDescription reportDescription = template().requestBody("direct:getReportDescription", testReportId,
+            ReportDescription.class);
+
+        assertNotNull("getReportDescriptions", reportDescription);
+        LOG.debug("getReportDescriptions: {}", reportDescription);
+        final ReportMetadata testReportMetadata = reportDescription.getReportMetadata();
+
+        // 2. executeSyncReport
+        // execute with no metadata
+        SyncReportResults reportResults = template().requestBodyAndHeader("direct:executeSyncReport",
+            testReportId, SalesforceEndpointConfig.INCLUDE_DETAILS, Boolean.TRUE, SyncReportResults.class);
+
+        assertNotNull("executeSyncReport", reportResults);
+        LOG.debug("executeSyncReport: {}", reportResults);
+
+        // execute with metadata
+        final Map<String, Object> headers = new HashMap<String, Object>();
+        headers.put(SalesforceEndpointConfig.INCLUDE_DETAILS, Boolean.FALSE);
+        Object body;
+        if (!bodyMetadata) {
+            headers.put(SalesforceEndpointConfig.REPORT_METADATA, testReportMetadata);
+            body = testReportId;
+        } else {
+            body = testReportMetadata;
+        }
+        reportResults = template().requestBodyAndHeaders("direct:executeSyncReport",
+            body, headers, SyncReportResults.class);
+
+        assertNotNull("executeSyncReport with metadata", reportResults);
+        LOG.debug("executeSyncReport with metadata: {}", reportResults);
+
+        // 3. executeAsyncReport
+        // execute with no metadata
+        ReportInstance reportInstance = template().requestBodyAndHeader("direct:executeAsyncReport",
+            testReportId, SalesforceEndpointConfig.INCLUDE_DETAILS, true, ReportInstance.class);
+
+        assertNotNull("executeAsyncReport", reportInstance);
+        LOG.debug("executeAsyncReport: {}", reportInstance);
+
+        // execute with metadata
+        headers.clear();
+        headers.put(SalesforceEndpointConfig.INCLUDE_DETAILS, "true");
+        if (!bodyMetadata) {
+            headers.put(SalesforceEndpointConfig.REPORT_METADATA, testReportMetadata);
+            body = testReportId;
+            bodyMetadata = true;
+        } else {
+            body = testReportMetadata;
+            bodyMetadata = false;
+        }
+        reportInstance = template().requestBodyAndHeaders("direct:executeAsyncReport",
+            body, headers, ReportInstance.class);
+
+        assertNotNull("executeAsyncReport with metadata", reportInstance);
+        LOG.debug("executeAsyncReport with metadata: {}", reportInstance);
+        final String testReportInstanceId = reportInstance.getId();
+
+        // 4. getReportInstances
+        final List reportInstances = template().requestBody("direct:getReportInstances", testReportId, List.class);
+
+        assertNotNull("getReportInstances", reportInstances);
+        assertFalse("getReportInstances empty", reportInstances.isEmpty());
+        LOG.debug("getReportInstances: {}", reportInstances);
+
+        // 5. getReportResults
+        // wait for the report to complete
+        boolean done = false;
+        int tries = 0;
+        AsyncReportResults asyncReportResults = null;
+        while (!done) {
+            asyncReportResults = template().requestBodyAndHeader("direct:getReportResults",
+                testReportId, SalesforceEndpointConfig.INSTANCE_ID, testReportInstanceId, AsyncReportResults.class);
+            done = asyncReportResults != null
+                && (asyncReportResults.getAttributes().getStatus() == ReportStatusEnum.Success
+                    || asyncReportResults.getAttributes().getStatus() == ReportStatusEnum.Error);
+            if (!done) {
+                // avoid flooding calls
+                Thread.sleep(RETRY_DELAY);
+                if (++tries > REPORT_RESULT_RETRIES) {
+                    final long retrySeconds = TimeUnit.SECONDS.convert(tries * RETRY_DELAY, TimeUnit.MILLISECONDS);
+                    fail("Async report result not available in " + retrySeconds + " seconds");
+                }
+            }
+        }
+
+        assertNotNull("getReportResults", asyncReportResults);
+        assertEquals("getReportResults status", ReportStatusEnum.Success,
+            asyncReportResults.getAttributes().getStatus());
+        LOG.debug("getReportResults: {}", asyncReportResults);
+
+        // 6. SalesforceReportResultsConverter tests
+        // defaults
+        String convertResults = template.requestBody("direct:convertResults", asyncReportResults, String.class);
+        assertNotNull("default convertResults", convertResults);
+        LOG.debug("Default options", convertResults);
+        LOG.debug("{}", convertResults);
+
+        // permutations of include details, include headers, include summary
+        final boolean[] values = new boolean[NUM_OPTIONS];
+        final int nIterations = (int) Math.pow(2, NUM_OPTIONS);
+
+        for (int i = 0; i < nIterations; i++) {
+
+            // toggle options
+            for (int j = 0; j < NUM_OPTIONS; j++) {
+                if (i % POWERS[j] == 0) {
+                    values[j] = !values[j];
+                }
+            }
+
+            log.debug("Options {} = {}", REPORT_OPTIONS, values);
+            headers.clear();
+            for (int j = 0; j < REPORT_OPTIONS.length; j++) {
+                headers.put(REPORT_OPTIONS[j], values[j]);
+            }
+            convertResults = template.requestBodyAndHeaders("direct:convertResults", asyncReportResults,
+                headers, String.class);
+
+            assertNotNull("convertResults", convertResults);
+            LOG.debug("{}", convertResults);
+        }
+    }
+
+    @Override
+    protected RouteBuilder doCreateRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+
+                // get Report SObject by DeveloperName
+                from("direct:queryReport")
+                    .to("salesforce:query?sObjectClass=" + QueryRecordsReport.class.getName());
+                
+                from("direct:getRecentReports")
+                    .to("salesforce:getRecentReports");
+
+                from("direct:getReportDescription")
+                    .to("salesforce:getReportDescription");
+                
+                from("direct:executeSyncReport")
+                    .to("salesforce:executeSyncReport");
+                
+                from("direct:executeAsyncReport")
+                    .to("salesforce:executeAsyncReport?includeDetails=true");
+                
+                from("direct:getReportInstances")
+                    .to("salesforce:getReportInstances");
+                
+                from("direct:getReportResults")
+                    .to("salesforce:getReportResults");
+
+                CsvDataFormat csv = new CsvDataFormat(CSVFormat.EXCEL);
+
+                // type converter test
+                from("direct:convertResults")
+                    .convertBodyTo(List.class)
+                    .marshal(csv);
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
index f136a33..28c6a5b 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java
@@ -26,7 +26,7 @@ import org.junit.Assert;
 
 public class LoginConfigHelper extends Assert {
 
-    private static final String TEST_LOGIN_PROPERTIES = "../test-salesforce-login.properties";
+    protected static final String TEST_LOGIN_PROPERTIES = "../test-salesforce-login.properties";
 
     public static SalesforceLoginConfig getLoginConfig() throws IOException {
 


[7/8] camel git commit: CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API

Posted by dh...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java
new file mode 100644
index 0000000..b1f039b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportExtendedMetadata.java
@@ -0,0 +1,55 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results extended metadata.
+ */
+public class ReportExtendedMetadata extends AbstractDTOBase {
+
+    private Map<String, GroupingColumnInfo> groupingColumnInfo;
+    private Map<String, DetailColumnInfo> detailColumnInfo;
+    private Map<String, AggregateColumnInfo> aggregateColumnInfo;
+
+    public Map<String, GroupingColumnInfo> getGroupingColumnInfo() {
+        return groupingColumnInfo;
+    }
+
+    public void setGroupingColumnInfo(Map<String, GroupingColumnInfo> groupingColumnInfo) {
+        this.groupingColumnInfo = groupingColumnInfo;
+    }
+
+    public Map<String, DetailColumnInfo> getDetailColumnInfo() {
+        return detailColumnInfo;
+    }
+
+    public void setDetailColumnInfo(Map<String, DetailColumnInfo> detailColumnInfo) {
+        this.detailColumnInfo = detailColumnInfo;
+    }
+
+    public Map<String, AggregateColumnInfo> getAggregateColumnInfo() {
+        return aggregateColumnInfo;
+    }
+
+    public void setAggregateColumnInfo(Map<String, AggregateColumnInfo> aggregateColumnInfo) {
+        this.aggregateColumnInfo = aggregateColumnInfo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java
new file mode 100644
index 0000000..bf600ae
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFactWithDetails.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results fact with details.
+ */
+public class ReportFactWithDetails extends AbstractDTOBase {
+
+    private ReportRow[] rows;
+    private SummaryValue[] aggregates;
+
+    public ReportRow[] getRows() {
+        return rows;
+    }
+
+    public void setRows(ReportRow[] rows) {
+        this.rows = rows;
+    }
+
+    public SummaryValue[] getAggregates() {
+        return aggregates;
+    }
+
+    public void setAggregates(SummaryValue[] aggregates) {
+        this.aggregates = aggregates;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java
new file mode 100644
index 0000000..17aa9cf
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFilter.java
@@ -0,0 +1,53 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report filter details DTO.
+ */
+public class ReportFilter extends AbstractDTOBase {
+
+    private String value;
+    private String column;
+    private String operator;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getColumn() {
+        return column;
+    }
+
+    public void setColumn(String column) {
+        this.column = column;
+    }
+
+    public String getOperator() {
+        return operator;
+    }
+
+    public void setOperator(String operator) {
+        this.operator = operator;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java
new file mode 100644
index 0000000..744b236
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportFormatEnum.java
@@ -0,0 +1,24 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report format enumeration.
+ */
+public enum ReportFormatEnum {
+    TABULAR, SUMMARY, MATRIX
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java
new file mode 100644
index 0000000..f69ae8d
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportInstance.java
@@ -0,0 +1,90 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+import org.joda.time.DateTime;
+
+/**
+ * Report instance DTO.
+ */
+public class ReportInstance extends AbstractDTOBase {
+
+    private String id;
+    private ReportStatusEnum status;
+    private String url;
+    private String ownerId;
+    private Boolean hasDetailRows;
+    private DateTime completionDate;
+    private DateTime requestDate;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public ReportStatusEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(ReportStatusEnum status) {
+        this.status = status;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getOwnerId() {
+        return ownerId;
+    }
+
+    public void setOwnerId(String ownerId) {
+        this.ownerId = ownerId;
+    }
+
+    public Boolean getHasDetailRows() {
+        return hasDetailRows;
+    }
+
+    public void setHasDetailRows(Boolean hasDetailRows) {
+        this.hasDetailRows = hasDetailRows;
+    }
+
+    public DateTime getCompletionDate() {
+        return completionDate;
+    }
+
+    public void setCompletionDate(DateTime completionDate) {
+        this.completionDate = completionDate;
+    }
+
+    public DateTime getRequestDate() {
+        return requestDate;
+    }
+
+    public void setRequestDate(DateTime requestDate) {
+        this.requestDate = requestDate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java
new file mode 100644
index 0000000..1ad0cff
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportMetadata.java
@@ -0,0 +1,143 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report metadata DTO.
+ */
+public class ReportMetadata extends AbstractDTOBase {
+
+    private String name;
+    private String id;
+    private String currency;
+    private ReportFormatEnum reportFormat;
+    private String developerName;
+    private ReportType reportType;
+    private String[] aggregates;
+    private GroupingInfo[] groupingsDown;
+    private GroupingInfo[] groupingsAcross;
+    private String reportBooleanFilter;
+    private ReportFilter[] reportFilters;
+    private String[] detailColumns;
+    private String[] historicalSnapshotDates;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    public void setCurrency(String currency) {
+        this.currency = currency;
+    }
+
+    public ReportFormatEnum getReportFormat() {
+        return reportFormat;
+    }
+
+    public void setReportFormat(ReportFormatEnum reportFormat) {
+        this.reportFormat = reportFormat;
+    }
+
+    public String getDeveloperName() {
+        return developerName;
+    }
+
+    public void setDeveloperName(String developerName) {
+        this.developerName = developerName;
+    }
+
+    public ReportType getReportType() {
+        return reportType;
+    }
+
+    public void setReportType(ReportType reportType) {
+        this.reportType = reportType;
+    }
+
+    public String[] getAggregates() {
+        return aggregates;
+    }
+
+    public void setAggregates(String[] aggregates) {
+        this.aggregates = aggregates;
+    }
+
+    public GroupingInfo[] getGroupingsDown() {
+        return groupingsDown;
+    }
+
+    public void setGroupingsDown(GroupingInfo[] groupingsDown) {
+        this.groupingsDown = groupingsDown;
+    }
+
+    public GroupingInfo[] getGroupingsAcross() {
+        return groupingsAcross;
+    }
+
+    public void setGroupingsAcross(GroupingInfo[] groupingsAcross) {
+        this.groupingsAcross = groupingsAcross;
+    }
+
+    public String getReportBooleanFilter() {
+        return reportBooleanFilter;
+    }
+
+    public void setReportBooleanFilter(String reportBooleanFilter) {
+        this.reportBooleanFilter = reportBooleanFilter;
+    }
+
+    public ReportFilter[] getReportFilters() {
+        return reportFilters;
+    }
+
+    public void setReportFilters(ReportFilter[] reportFilters) {
+        this.reportFilters = reportFilters;
+    }
+
+    public String[] getDetailColumns() {
+        return detailColumns;
+    }
+
+    public void setDetailColumns(String[] detailColumns) {
+        this.detailColumns = detailColumns;
+    }
+
+    public String[] getHistoricalSnapshotDates() {
+        return historicalSnapshotDates;
+    }
+
+    public void setHistoricalSnapshotDates(String[] historicalSnapshotDates) {
+        this.historicalSnapshotDates = historicalSnapshotDates;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java
new file mode 100644
index 0000000..5349dcc
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportRow.java
@@ -0,0 +1,35 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Reports fact map row.
+ */
+public class ReportRow extends AbstractDTOBase {
+
+    private SummaryValue[] dataCells;
+
+    public SummaryValue[] getDataCells() {
+        return dataCells;
+    }
+
+    public void setDataCells(SummaryValue[] dataCells) {
+        this.dataCells = dataCells;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java
new file mode 100644
index 0000000..871aa8e
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportStatusEnum.java
@@ -0,0 +1,24 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report status enumeration.
+ */
+public enum ReportStatusEnum {
+    New, Success, Running, Error
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java
new file mode 100644
index 0000000..9fd8b90
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportType.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type DTO.
+ */
+public class ReportType extends AbstractDTOBase {
+
+    private String type;
+    private String label;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java
new file mode 100644
index 0000000..b1f933b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumn.java
@@ -0,0 +1,62 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report categories columns.
+ */
+public class ReportTypeColumn extends AbstractDTOBase {
+
+    private String label;
+    private FilterValue[] filterValues;
+    private String dataType;
+    private Boolean filterable;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public FilterValue[] getFilterValues() {
+        return filterValues;
+    }
+
+    public void setFilterValues(FilterValue[] filterValues) {
+        this.filterValues = filterValues;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public Boolean getFilterable() {
+        return filterable;
+    }
+
+    public void setFilterable(Boolean filterable) {
+        this.filterable = filterable;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.java
new file mode 100644
index 0000000..fcd5c49
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeColumnCategory.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.component.salesforce.api.dto.analytics.reports;
+
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type metadata categories DTO.
+ */
+public class ReportTypeColumnCategory extends AbstractDTOBase {
+
+    private String label;
+    private Map<String, ReportTypeColumn> columns;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public Map<String, ReportTypeColumn> getColumns() {
+        return columns;
+    }
+
+    public void setColumns(Map<String, ReportTypeColumn> columns) {
+        this.columns = columns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java
new file mode 100644
index 0000000..9d849c8
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportTypeMetadata.java
@@ -0,0 +1,47 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report description report type DTO.
+ */
+public class ReportTypeMetadata extends AbstractDTOBase {
+
+    private ReportTypeColumnCategory[] categories;
+    private Map<String, List<FilterOperator>> dataTypeFilterOperatorMap;
+
+    public ReportTypeColumnCategory[] getCategories() {
+        return categories;
+    }
+
+    public void setCategories(ReportTypeColumnCategory[] categories) {
+        this.categories = categories;
+    }
+
+    public Map<String, List<FilterOperator>> getDataTypeFilterOperatorMap() {
+        return dataTypeFilterOperatorMap;
+    }
+
+    public void setDataTypeFilterOperatorMap(Map<String, List<FilterOperator>> dataTypeFilterOperatorMap) {
+        this.dataTypeFilterOperatorMap = dataTypeFilterOperatorMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java
new file mode 100644
index 0000000..34127c7
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SummaryValue.java
@@ -0,0 +1,58 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+
+/**
+ * Report results summary value DTO for data cells and aggregates.
+ */
+public class SummaryValue extends AbstractDTOBase {
+
+    public static final String VALUE_FIELD = "value";
+
+    private String label;
+
+    private Object value;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * Helper method for JSON un-marshaling.
+     * @param name field name, MUST be "value"
+     * @param value field value
+     * @throws java.lang.IllegalArgumentException if field name is not "value"
+     */
+    @JsonAnySetter
+    public void setAny(String name, Object value) throws IllegalArgumentException {
+        if (!VALUE_FIELD.equals(name)) {
+            throw new IllegalArgumentException(name);
+        }
+        this.value = value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.java
new file mode 100644
index 0000000..b2cc08d
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncAttributes.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.component.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report results Attributes.
+ */
+public class SyncAttributes extends AbstractAttributesBase {
+
+    private String describeUrl;
+    private String instancesUrl;
+
+    public String getDescribeUrl() {
+        return describeUrl;
+    }
+
+    public void setDescribeUrl(String describeUrl) {
+        this.describeUrl = describeUrl;
+    }
+
+    public String getInstancesUrl() {
+        return instancesUrl;
+    }
+
+    public void setInstancesUrl(String instancesUrl) {
+        this.instancesUrl = instancesUrl;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java
new file mode 100644
index 0000000..dead5e9
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/SyncReportResults.java
@@ -0,0 +1,34 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Sync Report results DTO.
+ */
+public class SyncReportResults extends AbstractReportResultsBase {
+
+    private SyncAttributes attributes;
+
+    public SyncAttributes getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(SyncAttributes attributes) {
+        this.attributes = attributes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
index a5b7893..efe09ce 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
@@ -49,7 +49,15 @@ public enum OperationName {
     GET_RESULTS("getResults"),
     CREATE_BATCH_QUERY("createBatchQuery"),
     GET_QUERY_RESULT_IDS("getQueryResultIds"),
-    GET_QUERY_RESULT("getQueryResult");
+    GET_QUERY_RESULT("getQueryResult"),
+    
+    // analytics API
+    GET_RECENT_REPORTS("getRecentReports"),
+    GET_REPORT_DESCRIPTION("getReportDescription"),
+    EXECUTE_SYNCREPORT("executeSyncReport"),
+    EXECUTE_ASYNCREPORT("executeAsyncReport"),
+    GET_REPORT_INSTANCES("getReportInstances"),
+    GET_REPORT_RESULTS("getReportResults");
 
     private final String value;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java
new file mode 100644
index 0000000..b40c8bb
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AnalyticsApiClient.java
@@ -0,0 +1,71 @@
+/**
+ * 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.salesforce.internal.client;
+
+import java.util.List;
+
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AbstractReportResultsBase;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.RecentReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+
+/**
+ * Client interface for Analytics API.
+ */
+public interface AnalyticsApiClient {
+
+    // Report operations
+
+    public interface RecentReportsResponseCallback {
+        void onResponse(List<RecentReport> reportDescription, SalesforceException ex);
+    }
+
+    public interface ReportDescriptionResponseCallback {
+        void onResponse(ReportDescription reportDescription, SalesforceException ex);
+    }
+
+    public interface ReportResultsResponseCallback {
+        void onResponse(AbstractReportResultsBase reportResults, SalesforceException ex);
+    }
+
+    public interface ReportInstanceResponseCallback {
+        void onResponse(ReportInstance reportInstance, SalesforceException ex);
+    }
+
+    public interface ReportInstanceListResponseCallback {
+        void onResponse(List<ReportInstance> reportInstances, SalesforceException ex);
+    }
+
+    void getRecentReports(RecentReportsResponseCallback callback);
+
+    void getReportDescription(String reportId,
+                              ReportDescriptionResponseCallback callback);
+
+    void executeSyncReport(String reportId, Boolean includeDetails, ReportMetadata reportFilter,
+                           ReportResultsResponseCallback callback);
+
+    void executeAsyncReport(String reportId, Boolean includeDetails, ReportMetadata reportFilter,
+                           ReportInstanceResponseCallback callback);
+
+    void getReportInstances(String reportId,
+                           ReportInstanceListResponseCallback callback);
+
+    void getReportResults(String reportId, String instanceId,
+                           ReportResultsResponseCallback callback);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java
new file mode 100644
index 0000000..1041f7f
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultAnalyticsApiClient.java
@@ -0,0 +1,339 @@
+/**
+ * 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.salesforce.internal.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.RestError;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AsyncReportResults;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.RecentReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.SyncReportResults;
+import org.apache.camel.component.salesforce.internal.SalesforceSession;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+import org.eclipse.jetty.util.StringUtil;
+
+/**
+ * Default implementation of {@link org.apache.camel.component.salesforce.internal.client.AnalyticsApiClient}.
+ */
+public class DefaultAnalyticsApiClient extends AbstractClientBase implements AnalyticsApiClient {
+
+    private static final String TOKEN_PREFIX = "Bearer ";
+    private static final String INCLUDE_DETAILS_QUERY_PARAM = "?includeDetails=";
+    private ObjectMapper objectMapper;
+
+
+    public DefaultAnalyticsApiClient(String version, SalesforceSession session, HttpClient httpClient) throws SalesforceException {
+        super(version, session, httpClient);
+
+        objectMapper = new ObjectMapper();
+    }
+
+    @Override
+    public void getRecentReports(final RecentReportsResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET, reportsUrl());
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public void onResponse(InputStream response, SalesforceException ex) {
+                List<RecentReport> recentReports = null;
+                if (response != null) {
+                    try {
+                        recentReports = unmarshalResponse(response, contentExchange,
+                            new TypeReference<List<RecentReport>>() {
+                            }
+                        );
+                    } catch (SalesforceException e) {
+                        ex = e;
+                    }
+                }
+                callback.onResponse(recentReports, ex);
+            }
+        });
+    }
+
+    @Override
+    public void getReportDescription(String reportId, final ReportDescriptionResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET, reportsDescribeUrl(reportId));
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                ReportDescription reportDescription = null;
+                try {
+                    reportDescription = unmarshalResponse(response, contentExchange, ReportDescription.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportDescription, ex);
+            }
+        });
+    }
+
+    @Override
+    public void executeSyncReport(String reportId, Boolean includeDetails, ReportMetadata reportMetadata,
+                                  final ReportResultsResponseCallback callback) {
+
+        final boolean useGet = reportMetadata == null;
+        final ContentExchange contentExchange = getContentExchange(
+            useGet ? HttpMethods.GET : HttpMethods.POST, reportsUrl(reportId, includeDetails));
+
+        // set POST data
+        if (!useGet) {
+            try {
+                // wrap reportMetadata in a map
+                final HashMap<String, Object> request = new HashMap<String, Object>();
+                request.put("reportMetadata", reportMetadata);
+                marshalRequest(request, contentExchange);
+            } catch (SalesforceException e) {
+                callback.onResponse(null, e);
+                return;
+            }
+        }
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                SyncReportResults reportResults = null;
+                try {
+                    reportResults = unmarshalResponse(response, contentExchange, SyncReportResults.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportResults, ex);
+            }
+        });
+    }
+
+    @Override
+    public void executeAsyncReport(String reportId, Boolean includeDetails, ReportMetadata reportMetadata,
+                                   final ReportInstanceResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.POST,
+            reportInstancesUrl(reportId, includeDetails));
+
+        // set POST data
+        if (reportMetadata != null) {
+            try {
+                // wrap reportMetadata in a map
+                final HashMap<String, Object> request = new HashMap<String, Object>();
+                request.put("reportMetadata", reportMetadata);
+                marshalRequest(request, contentExchange);
+            } catch (SalesforceException e) {
+                callback.onResponse(null, e);
+                return;
+            }
+        }
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                ReportInstance reportInstance = null;
+                try {
+                    reportInstance = unmarshalResponse(response, contentExchange, ReportInstance.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportInstance, ex);
+            }
+        });
+    }
+
+    @Override
+    public void getReportInstances(String reportId, final ReportInstanceListResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET, reportInstancesUrl(reportId));
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public void onResponse(InputStream response, SalesforceException ex) {
+                List<ReportInstance> reportInstances = null;
+                if (response != null) {
+                    try {
+                        reportInstances = unmarshalResponse(response, contentExchange,
+                            new TypeReference<List<ReportInstance>>() {
+                            }
+                        );
+                    } catch (SalesforceException e) {
+                        ex = e;
+                    }
+                }
+                callback.onResponse(reportInstances, ex);
+            }
+        });
+    }
+
+    @Override
+    public void getReportResults(String reportId, String instanceId, final ReportResultsResponseCallback callback) {
+
+        final ContentExchange contentExchange = getContentExchange(HttpMethods.GET,
+            reportInstancesUrl(reportId, instanceId));
+
+        doHttpRequest(contentExchange, new ClientResponseCallback() {
+            @Override
+            public void onResponse(InputStream response, SalesforceException ex) {
+                AsyncReportResults reportResults = null;
+                try {
+                    reportResults = unmarshalResponse(response, contentExchange, AsyncReportResults.class);
+                } catch (SalesforceException e) {
+                    ex = e;
+                }
+                callback.onResponse(reportResults, ex);
+            }
+        });
+    }
+
+    private String reportsUrl() {
+        // NOTE the prefix 'v' for the version number
+        return instanceUrl + "/services/data/v" + version + "/analytics/reports";
+    }
+
+    private String reportsDescribeUrl(String reportId) {
+        return reportsUrl(reportId) + "/describe";
+    }
+
+    private String reportsUrl(String reportId) {
+        return reportsUrl() +  "/" + reportId;
+    }
+
+    private String reportsUrl(String reportId, Boolean includeDetails) {
+        return includeDetails == null ? reportsUrl(reportId)
+                : reportsUrl(reportId) + INCLUDE_DETAILS_QUERY_PARAM + includeDetails;
+    }
+
+    private String reportInstancesUrl(String reportId) {
+        return reportsUrl(reportId) + "/instances";
+    }
+
+    private String reportInstancesUrl(String reportId, Boolean includeDetails) {
+        return includeDetails == null ? reportInstancesUrl(reportId)
+            : reportInstancesUrl(reportId) + INCLUDE_DETAILS_QUERY_PARAM + includeDetails;
+    }
+
+    private String reportInstancesUrl(String reportId, String instanceId) {
+        return reportInstancesUrl(reportId) + "/" + instanceId;
+    }
+
+    @Override
+    protected void setAccessToken(HttpExchange httpExchange) {
+        httpExchange.setRequestHeader(HttpHeaders.AUTHORIZATION, TOKEN_PREFIX + accessToken);
+    }
+
+    @Override
+    protected SalesforceException createRestException(ContentExchange httpExchange, String reason) {
+        final int statusCode = httpExchange.getResponseStatus();
+        String responseContent = null;
+        try {
+            responseContent = httpExchange.getResponseContent();
+            if (responseContent != null) {
+                // unmarshal RestError
+                final List<RestError> errors = objectMapper.readValue(responseContent,
+                    new TypeReference<List<RestError>>() {
+                    });
+                return new SalesforceException(errors, statusCode);
+            }
+        } catch (UnsupportedEncodingException e) {
+            // log and ignore
+            String msg = "Unexpected Error parsing JSON error response body + ["
+                + responseContent + "] : " + e.getMessage();
+            log.warn(msg, e);
+        } catch (IOException e) {
+            // log and ignore
+            String msg = "Unexpected Error parsing JSON error response body + ["
+                + responseContent + "] : " + e.getMessage();
+            log.warn(msg, e);
+        }
+
+        // just report HTTP status info
+        return new SalesforceException("Unexpected error: " + reason + ", with content: " + responseContent,
+            statusCode);
+    }
+
+    @Override
+    protected void doHttpRequest(ContentExchange request, ClientResponseCallback callback) {
+
+        // set access token for all requests
+        setAccessToken(request);
+
+        // set request and response content type and charset, which is always JSON for analytics API
+        request.setRequestHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_UTF8);
+        request.setRequestHeader(HttpHeaders.ACCEPT, APPLICATION_JSON_UTF8);
+        request.setRequestHeader(HttpHeaders.ACCEPT_CHARSET, StringUtil.__UTF8);
+
+        super.doHttpRequest(request, callback);
+    }
+
+    private void marshalRequest(Object input, ContentExchange request) throws SalesforceException {
+        try {
+            request.setRequestContent(new ByteArrayBuffer(objectMapper.writeValueAsBytes(input)));
+        } catch (IOException e) {
+            throw new SalesforceException(
+                String.format("Error marshaling request for {%s:%s} : %s",
+                    request.getMethod(), request.getRequestURI(), e.getMessage()),
+                e);
+        }
+    }
+
+    private <T> T unmarshalResponse(InputStream response, ContentExchange request,
+                                      TypeReference<T> responseTypeReference)
+        throws SalesforceException {
+
+        try {
+            return objectMapper.readValue(response, responseTypeReference);
+        } catch (IOException e) {
+            throw new SalesforceException(
+                String.format("Error unmarshaling response {%s:%s} : %s",
+                    request.getMethod(), request.getRequestURI(), e.getMessage()),
+                e);
+        }
+    }
+
+    private <T> T unmarshalResponse(InputStream response, ContentExchange request, Class<T> responseClass)
+        throws SalesforceException {
+
+        if (response == null) {
+            return null;
+        }
+
+        try {
+            return objectMapper.readValue(response, responseClass);
+        } catch (IOException e) {
+            throw new SalesforceException(
+                String.format("Error unmarshaling response {%s:%s} : %s",
+                    request.getMethod(), request.getRequestURI(), e.getMessage()),
+                e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
index 834ea51..352005a 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
@@ -64,7 +64,7 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor
 
         final PayloadFormat payloadFormat = endpoint.getConfiguration().getFormat();
 
-        this.restClient = new DefaultRestClient(httpClient, endpointConfigMap.get(API_VERSION),
+        this.restClient = new DefaultRestClient(httpClient, (String) endpointConfigMap.get(API_VERSION),
                 payloadFormat, session);
 
         this.classMap = endpoint.getComponent().getClassMap();
@@ -151,19 +151,19 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor
                 processApexCall(exchange, callback);
                 break;
             default:
-                throw new SalesforceException("Unknow operation name: " + operationName, null);
+                throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
             }
         } catch (SalesforceException e) {
             exchange.setException(new SalesforceException(
                     String.format("Error processing %s: [%s] \"%s\"",
-                            operationName, e.getStatusCode(), e.getMessage()),
+                            operationName.value(), e.getStatusCode(), e.getMessage()),
                     e));
             callback.done(true);
             return true;
         } catch (RuntimeException e) {
             exchange.setException(new SalesforceException(
                     String.format("Unexpected Error processing %s: \"%s\"",
-                            operationName, e.getMessage()),
+                            operationName.value(), e.getMessage()),
                     e));
             callback.done(true);
             return true;
@@ -446,7 +446,7 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor
     private void processQuery(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
         final String sObjectQuery = getParameter(SOBJECT_QUERY, exchange, USE_BODY, NOT_OPTIONAL);
 
-        // use sObject name to load class
+        // use custom response class property
         setResponseClass(exchange, null);
 
         restClient.query(sObjectQuery, new RestClient.ResponseCallback() {

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
index db5c66b..151d24d 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
@@ -20,6 +20,8 @@ import java.util.Map;
 
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.component.salesforce.SalesforceComponent;
 import org.apache.camel.component.salesforce.SalesforceEndpoint;
 import org.apache.camel.component.salesforce.api.SalesforceException;
@@ -39,7 +41,7 @@ public abstract class AbstractSalesforceProcessor implements SalesforceProcessor
     protected final Logger log = LoggerFactory.getLogger(this.getClass());
 
     protected final SalesforceEndpoint endpoint;
-    protected final Map<String, String> endpointConfigMap;
+    protected final Map<String, Object> endpointConfigMap;
 
     protected final OperationName operationName;
     protected final SalesforceSession session;
@@ -59,24 +61,65 @@ public abstract class AbstractSalesforceProcessor implements SalesforceProcessor
     public abstract boolean process(Exchange exchange, AsyncCallback callback);
 
     /**
-     * Gets value for a parameter from header, endpoint config, or exchange body (optional).
+     * Gets String value for a parameter from header, endpoint config, or exchange body (optional).
      *
-     * @param exchange      exchange to inspect
-     * @param convertInBody converts In body to String value if true
-     * @param propName      name of property
-     * @param optional      if {@code true} returns null, otherwise throws RestException
+     * @param exchange          exchange to inspect
+     * @param convertInBody     converts In body to String value if true
+     * @param propName          name of property
+     * @param optional          if {@code true} returns null, otherwise throws RestException
      * @return value of property, or {@code null} for optional parameters if not found.
      * @throws org.apache.camel.component.salesforce.api.SalesforceException
-     *          if the property can't be found.
+     *          if the property can't be found or on conversion errors.
      */
     protected final String getParameter(String propName, Exchange exchange, boolean convertInBody, boolean optional) throws SalesforceException {
-        String propValue = exchange.getIn().getHeader(propName, String.class);
-        propValue = propValue == null ? endpointConfigMap.get(propName) : propValue;
-        propValue = (propValue == null && convertInBody) ? exchange.getIn().getBody(String.class) : propValue;
+        return getParameter(propName, exchange, convertInBody, optional, String.class);
+    }
+
+    /**
+     * Gets value for a parameter from header, endpoint config, or exchange body (optional).
+     *
+     * @param exchange          exchange to inspect
+     * @param convertInBody     converts In body to parameterClass value if true
+     * @param propName          name of property
+     * @param optional          if {@code true} returns null, otherwise throws RestException
+     * @param parameterClass    parameter type
+     * @return value of property, or {@code null} for optional parameters if not found.
+     * @throws org.apache.camel.component.salesforce.api.SalesforceException
+     *          if the property can't be found or on conversion errors.
+     */
+    protected final <T> T getParameter(String propName, Exchange exchange, boolean convertInBody, boolean optional,
+                                       Class<T> parameterClass) throws SalesforceException {
+
+        final Message in = exchange.getIn();
+        T propValue = in.getHeader(propName, parameterClass);
+
+        if (propValue == null) {
+            // check if type conversion failed
+            if (in.getHeader(propName) != null) {
+                throw new IllegalArgumentException("Header " + propName
+                    + " could not be converted to type " + parameterClass.getName());
+            }
+
+            final Object value = endpointConfigMap.get(propName);
+
+            if (value == null || parameterClass.isInstance(value)) {
+                propValue = parameterClass.cast(value);
+            } else {
+
+                try {
+                    propValue = exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterClass, value);
+                } catch (NoTypeConversionAvailableException e) {
+                    throw new SalesforceException(e);
+                }
+            }
+        }
+
+        propValue = (propValue == null && convertInBody) ? in.getBody(parameterClass) : propValue;
 
         // error if property was not set
         if (propValue == null && !optional) {
-            String msg = "Missing property " + propName;
+            String msg = "Missing property " + propName
+                + (convertInBody ? ", message body could not be converted to type " + parameterClass.getName() : "");
             throw new SalesforceException(msg, null);
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
new file mode 100644
index 0000000..846bd62
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
@@ -0,0 +1,227 @@
+/**
+ * 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.salesforce.internal.processor;
+
+import java.util.List;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.salesforce.SalesforceEndpoint;
+import org.apache.camel.component.salesforce.SalesforceEndpointConfig;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AbstractReportResultsBase;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.RecentReport;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportDescription;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportInstance;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.internal.client.AnalyticsApiClient;
+import org.apache.camel.component.salesforce.internal.client.DefaultAnalyticsApiClient;
+import org.apache.camel.util.ServiceHelper;
+
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.INCLUDE_DETAILS;
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.INSTANCE_ID;
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.REPORT_ID;
+import static org.apache.camel.component.salesforce.SalesforceEndpointConfig.REPORT_METADATA;
+
+/**
+ * Exchange processor for Analytics API.
+ */
+public class AnalyticsApiProcessor extends AbstractSalesforceProcessor {
+
+    private AnalyticsApiClient analyticsClient;
+
+    public AnalyticsApiProcessor(SalesforceEndpoint endpoint) throws SalesforceException {
+        super(endpoint);
+
+        this.analyticsClient = new DefaultAnalyticsApiClient(
+            (String) endpointConfigMap.get(SalesforceEndpointConfig.API_VERSION), session, httpClient);
+    }
+
+    @Override
+    public boolean process(final Exchange exchange, final AsyncCallback callback) {
+        boolean done = false;
+
+        try {
+            switch (operationName) {
+            case GET_RECENT_REPORTS:
+                processGetRecentReports(exchange, callback);
+                break;
+            case GET_REPORT_DESCRIPTION:
+                processGetReportDescription(exchange, callback);
+                break;
+            case EXECUTE_SYNCREPORT:
+                processExecuteSyncReport(exchange, callback);
+                break;
+            case EXECUTE_ASYNCREPORT:
+                processExecuteAsyncReport(exchange, callback);
+                break;
+            case GET_REPORT_INSTANCES:
+                processGetReportInstances(exchange, callback);
+                break;
+            case GET_REPORT_RESULTS:
+                processGetReportResults(exchange, callback);
+                break;
+            default:
+                throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
+            }
+        } catch (SalesforceException e) {
+            exchange.setException(new SalesforceException(
+                    String.format("Error processing %s: [%s] \"%s\"",
+                            operationName.value(), e.getStatusCode(), e.getMessage()), e));
+            callback.done(true);
+            done = true;
+        } catch (RuntimeException e) {
+            exchange.setException(new SalesforceException(
+                    String.format("Unexpected Error processing %s: \"%s\"",
+                            operationName.value(), e.getMessage()), e));
+            callback.done(true);
+            done = true;
+        }
+
+        // continue routing asynchronously if false
+        return done;
+    }
+
+    private void processGetRecentReports(final Exchange exchange, final AsyncCallback callback) {
+
+        analyticsClient.getRecentReports(new AnalyticsApiClient.RecentReportsResponseCallback() {
+            @Override
+            public void onResponse(List<RecentReport> reportDescription, SalesforceException ex) {
+                processResponse(exchange, reportDescription, ex, callback);
+            }
+        });
+    }
+
+    private void processGetReportDescription(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        final String reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+
+        analyticsClient.getReportDescription(reportId, new AnalyticsApiClient.ReportDescriptionResponseCallback() {
+            @Override
+            public void onResponse(ReportDescription reportDescription, SalesforceException ex) {
+                processResponse(exchange, reportDescription, ex, callback);
+            }
+        });
+    }
+
+    private void processExecuteSyncReport(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        String reportId;
+        final Boolean includeDetails = getParameter(INCLUDE_DETAILS, exchange, IGNORE_BODY, IS_OPTIONAL, Boolean.class);
+
+        // try getting report metadata from body first
+        ReportMetadata reportMetadata = exchange.getIn().getBody(ReportMetadata.class);
+        if (reportMetadata != null) {
+            reportId = reportMetadata.getId();
+            if (reportId == null) {
+                reportId = getParameter(REPORT_ID, exchange, IGNORE_BODY, NOT_OPTIONAL);
+            }
+        } else {
+            reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+            reportMetadata = getParameter(REPORT_METADATA, exchange, IGNORE_BODY, IS_OPTIONAL,
+                ReportMetadata.class);
+        }
+
+        analyticsClient.executeSyncReport(reportId, includeDetails, reportMetadata,
+            new AnalyticsApiClient.ReportResultsResponseCallback() {
+                @Override
+                public void onResponse(AbstractReportResultsBase reportResults, SalesforceException ex) {
+                    processResponse(exchange, reportResults, ex, callback);
+                }
+            });
+    }
+
+    private void processExecuteAsyncReport(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        String reportId;
+        final Boolean includeDetails = getParameter(INCLUDE_DETAILS, exchange, IGNORE_BODY, IS_OPTIONAL, Boolean.class);
+
+        // try getting report metadata from body first
+        ReportMetadata reportMetadata = exchange.getIn().getBody(ReportMetadata.class);
+        if (reportMetadata != null) {
+            reportId = reportMetadata.getId();
+            if (reportId == null) {
+                reportId = getParameter(REPORT_ID, exchange, IGNORE_BODY, NOT_OPTIONAL);
+            }
+        } else {
+            reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+            reportMetadata = getParameter(REPORT_METADATA, exchange, IGNORE_BODY, IS_OPTIONAL,
+                ReportMetadata.class);
+        }
+
+        analyticsClient.executeAsyncReport(reportId, includeDetails, reportMetadata,
+            new AnalyticsApiClient.ReportInstanceResponseCallback() {
+                @Override
+                public void onResponse(ReportInstance reportInstance, SalesforceException ex) {
+                    processResponse(exchange, reportInstance, ex, callback);
+                }
+            });
+    }
+
+    private void processGetReportInstances(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        final String reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+
+        analyticsClient.getReportInstances(reportId, new AnalyticsApiClient.ReportInstanceListResponseCallback() {
+            @Override
+            public void onResponse(List<ReportInstance> reportInstances, SalesforceException ex) {
+                processResponse(exchange, reportInstances, ex, callback);
+            }
+        });
+    }
+
+    private void processGetReportResults(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
+
+        final String reportId = getParameter(REPORT_ID, exchange, USE_BODY, NOT_OPTIONAL);
+        final String instanceId = getParameter(INSTANCE_ID, exchange, IGNORE_BODY, NOT_OPTIONAL);
+
+        analyticsClient.getReportResults(reportId, instanceId, new AnalyticsApiClient.ReportResultsResponseCallback() {
+            @Override
+            public void onResponse(AbstractReportResultsBase reportResults, SalesforceException ex) {
+                processResponse(exchange, reportResults, ex, callback);
+            }
+        });
+    }
+
+    private void processResponse(Exchange exchange, Object body, SalesforceException ex, AsyncCallback callback) {
+        final Message out = exchange.getOut();
+        if (ex != null) {
+            exchange.setException(ex);
+        } else {
+            out.setBody(body);
+        }
+
+        // copy headers and attachments
+        out.getHeaders().putAll(exchange.getIn().getHeaders());
+        out.getAttachments().putAll(exchange.getIn().getAttachments());
+
+        // signal exchange completion
+        callback.done(false);
+    }
+
+    @Override
+    public void start() throws Exception {
+        ServiceHelper.startService(analyticsClient);
+    }
+
+    @Override
+    public void stop() throws Exception {
+        // stop the client
+        ServiceHelper.stopService(analyticsClient);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
index 80d382d..f83ad9d 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
@@ -51,7 +51,7 @@ public class BulkApiProcessor extends AbstractSalesforceProcessor {
         super(endpoint);
 
         this.bulkClient = new DefaultBulkApiClient(
-                endpointConfigMap.get(SalesforceEndpointConfig.API_VERSION), session, httpClient);
+            (String) endpointConfigMap.get(SalesforceEndpointConfig.API_VERSION), session, httpClient);
     }
 
     @Override
@@ -97,24 +97,24 @@ public class BulkApiProcessor extends AbstractSalesforceProcessor {
                 processGetQueryResult(exchange, callback);
                 break;
             default:
-                throw new SalesforceException("Unknow operation name: " + operationName, null);
+                throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
             }
         } catch (SalesforceException e) {
             exchange.setException(new SalesforceException(
                     String.format("Error processing %s: [%s] \"%s\"",
-                            operationName, e.getStatusCode(), e.getMessage()), e));
+                            operationName.value(), e.getStatusCode(), e.getMessage()), e));
             callback.done(true);
             done = true;
         } catch (InvalidPayloadException e) {
             exchange.setException(new SalesforceException(
                     String.format("Unexpected Error processing %s: \"%s\"",
-                            operationName, e.getMessage()), e));
+                            operationName.value(), e.getMessage()), e));
             callback.done(true);
             done = true;
         } catch (RuntimeException e) {
             exchange.setException(new SalesforceException(
                     String.format("Unexpected Error processing %s: \"%s\"",
-                            operationName, e.getMessage()), e));
+                            operationName.value(), e.getMessage()), e));
             callback.done(true);
             done = true;
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter b/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
new file mode 100644
index 0000000..4488642
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/resources/META-INF/services/org/apache/camel/TypeConverter
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.camel.component.salesforce.api.SalesforceReportResultsToListConverter


[8/8] camel git commit: CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API

Posted by dh...@apache.org.
CAMEL-8397: Added support for Salesforce1 Anayltics reporting API, minor refactor, added missing Salesforce fields for latest API


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b508c4dc
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b508c4dc
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b508c4dc

Branch: refs/heads/camel-2.14.x
Commit: b508c4dc6d97ba8f7e12657e7e9a9f6ec53b8eb0
Parents: ef5614d
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Wed Jun 24 18:14:02 2015 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Wed Jun 24 20:35:35 2015 -0700

----------------------------------------------------------------------
 .../camel-salesforce-component/pom.xml          |   5 +
 .../salesforce/SalesforceEndpointConfig.java    |  59 ++-
 .../salesforce/SalesforceProducer.java          |  20 +-
 .../SalesforceReportResultsToListConverter.java | 515 +++++++++++++++++++
 .../salesforce/api/dto/PickListValue.java       |   2 +-
 .../salesforce/api/dto/RestResources.java       |   9 +
 .../salesforce/api/dto/SObjectField.java        |   9 +
 .../reports/AbstractAttributesBase.java         |  53 ++
 .../reports/AbstractReportResultsBase.java      |  91 ++++
 .../analytics/reports/AggregateColumnInfo.java  |  42 ++
 .../dto/analytics/reports/AsyncAttributes.java  |  71 +++
 .../analytics/reports/AsyncReportResults.java   |  33 ++
 .../analytics/reports/ColumnSortOrderEnum.java  |  24 +
 .../analytics/reports/DateGranularityEnum.java  |  73 +++
 .../dto/analytics/reports/DetailColumnInfo.java |  44 ++
 .../dto/analytics/reports/FilterOperator.java   |  44 ++
 .../api/dto/analytics/reports/FilterValue.java  |  44 ++
 .../api/dto/analytics/reports/FormatEnum.java   |  57 ++
 .../analytics/reports/GroupingColumnInfo.java   |  33 ++
 .../api/dto/analytics/reports/GroupingInfo.java |  62 +++
 .../dto/analytics/reports/GroupingValue.java    |  72 +++
 .../api/dto/analytics/reports/Groupings.java    |  35 ++
 .../analytics/reports/QueryRecordsReport.java   |  40 ++
 .../api/dto/analytics/reports/RecentReport.java |  71 +++
 .../api/dto/analytics/reports/Report.java       | 100 ++++
 .../analytics/reports/ReportDescription.java    |  53 ++
 .../reports/ReportExtendedMetadata.java         |  55 ++
 .../reports/ReportFactWithDetails.java          |  44 ++
 .../api/dto/analytics/reports/ReportFilter.java |  53 ++
 .../dto/analytics/reports/ReportFormatEnum.java |  24 +
 .../dto/analytics/reports/ReportInstance.java   |  90 ++++
 .../dto/analytics/reports/ReportMetadata.java   | 143 +++++
 .../api/dto/analytics/reports/ReportRow.java    |  35 ++
 .../dto/analytics/reports/ReportStatusEnum.java |  24 +
 .../api/dto/analytics/reports/ReportType.java   |  44 ++
 .../dto/analytics/reports/ReportTypeColumn.java |  62 +++
 .../reports/ReportTypeColumnCategory.java       |  46 ++
 .../analytics/reports/ReportTypeMetadata.java   |  47 ++
 .../api/dto/analytics/reports/SummaryValue.java |  58 +++
 .../dto/analytics/reports/SyncAttributes.java   |  43 ++
 .../analytics/reports/SyncReportResults.java    |  34 ++
 .../salesforce/internal/OperationName.java      |  10 +-
 .../internal/client/AnalyticsApiClient.java     |  71 +++
 .../client/DefaultAnalyticsApiClient.java       | 339 ++++++++++++
 .../processor/AbstractRestProcessor.java        |  10 +-
 .../processor/AbstractSalesforceProcessor.java  |  65 ++-
 .../processor/AnalyticsApiProcessor.java        | 227 ++++++++
 .../internal/processor/BulkApiProcessor.java    |  10 +-
 .../services/org/apache/camel/TypeConverter     |  18 +
 .../salesforce/AnalyticsApiIntegrationTest.java | 285 ++++++++++
 .../component/salesforce/LoginConfigHelper.java |   2 +-
 51 files changed, 3473 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/pom.xml b/components/camel-salesforce/camel-salesforce-component/pom.xml
index acda40d..5be895a 100644
--- a/components/camel-salesforce/camel-salesforce-component/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-component/pom.xml
@@ -112,6 +112,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-csv</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-server</artifactId>
       <version>${jetty-version}</version>

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
index 39b860a..f8f7e9b 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
 import org.apache.camel.component.salesforce.api.dto.bulk.ContentType;
 import org.apache.camel.component.salesforce.internal.PayloadFormat;
 import org.apache.camel.component.salesforce.internal.dto.NotifyForFieldsEnum;
@@ -63,6 +64,12 @@ public class SalesforceEndpointConfig implements Cloneable {
     public static final String JOB_ID = "jobId";
     public static final String BATCH_ID = "batchId";
     public static final String RESULT_ID = "resultId";
+    
+    // parameters for Analytics API
+    public static final String REPORT_ID = "reportId";
+    public static final String INCLUDE_DETAILS = "includeDetails";
+    public static final String REPORT_METADATA = "reportMetadata";
+    public static final String INSTANCE_ID = "instanceId";
 
     // general properties
     @UriParam
@@ -121,6 +128,16 @@ public class SalesforceEndpointConfig implements Cloneable {
     private Boolean notifyForOperationDelete;
     @UriParam
     private Boolean notifyForOperationUndelete;
+    
+    // Analytics API properties
+    @UriParam
+    private String reportId;
+    @UriParam
+    private Boolean includeDetails;
+    @UriParam
+    private ReportMetadata reportMetadata;
+    @UriParam
+    private String instanceId;
 
     // Jetty HttpClient, set using reference
     @UriParam
@@ -336,6 +353,38 @@ public class SalesforceEndpointConfig implements Cloneable {
         this.notifyForOperationUndelete = notifyForOperationUndelete;
     }
 
+    public String getReportId() {
+        return reportId;
+    }
+
+    public void setReportId(String reportId) {
+        this.reportId = reportId;
+    }
+
+    public Boolean getIncludeDetails() {
+        return includeDetails;
+    }
+
+    public void setIncludeDetails(Boolean includeDetails) {
+        this.includeDetails = includeDetails;
+    }
+
+    public ReportMetadata getReportMetadata() {
+        return reportMetadata;
+    }
+
+    public void setReportMetadata(ReportMetadata reportMetadata) {
+        this.reportMetadata = reportMetadata;
+    }
+
+    public String getInstanceId() {
+        return instanceId;
+    }
+
+    public void setInstanceId(String instanceId) {
+        this.instanceId = instanceId;
+    }
+
     public void setHttpClient(HttpClient httpClient) {
         this.httpClient = httpClient;
     }
@@ -344,9 +393,9 @@ public class SalesforceEndpointConfig implements Cloneable {
         return httpClient;
     }
 
-    public Map<String, String> toValueMap() {
+    public Map<String, Object> toValueMap() {
 
-        final Map<String, String> valueMap = new HashMap<String, String>();
+        final Map<String, Object> valueMap = new HashMap<String, Object>();
         valueMap.put(FORMAT, format.toString().toLowerCase());
         valueMap.put(API_VERSION, apiVersion);
 
@@ -370,6 +419,12 @@ public class SalesforceEndpointConfig implements Cloneable {
         valueMap.put(JOB_ID, jobId);
         valueMap.put(BATCH_ID, batchId);
         valueMap.put(RESULT_ID, resultId);
+        
+        // add analytics API properties
+        valueMap.put(REPORT_ID, reportId);
+        valueMap.put(INCLUDE_DETAILS, includeDetails);
+        valueMap.put(REPORT_METADATA, reportMetadata);
+        valueMap.put(INSTANCE_ID, instanceId);
 
         return Collections.unmodifiableMap(valueMap);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
index 42c1bfe..55b1bf0 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
@@ -21,6 +21,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.component.salesforce.api.SalesforceException;
 import org.apache.camel.component.salesforce.internal.OperationName;
 import org.apache.camel.component.salesforce.internal.PayloadFormat;
+import org.apache.camel.component.salesforce.internal.processor.AnalyticsApiProcessor;
 import org.apache.camel.component.salesforce.internal.processor.BulkApiProcessor;
 import org.apache.camel.component.salesforce.internal.processor.JsonRestProcessor;
 import org.apache.camel.component.salesforce.internal.processor.SalesforceProcessor;
@@ -42,8 +43,11 @@ public class SalesforceProducer extends DefaultAsyncProducer {
         final PayloadFormat payloadFormat = endpointConfig.getFormat();
 
         // check if its a Bulk Operation
-        if (isBulkOperation(endpoint.getOperationName())) {
+        final OperationName operationName = endpoint.getOperationName();
+        if (isBulkOperation(operationName)) {
             processor = new BulkApiProcessor(endpoint);
+        } else if (isAnalyticsOperation(operationName)) {
+            processor = new AnalyticsApiProcessor(endpoint);
         } else {
             // create an appropriate processor
             if (payloadFormat == PayloadFormat.JSON) {
@@ -75,6 +79,20 @@ public class SalesforceProducer extends DefaultAsyncProducer {
         }
     }
 
+    private boolean isAnalyticsOperation(OperationName operationName) {
+        switch (operationName) {
+        case GET_RECENT_REPORTS:
+        case GET_REPORT_DESCRIPTION:
+        case EXECUTE_SYNCREPORT:
+        case EXECUTE_ASYNCREPORT:
+        case GET_REPORT_INSTANCES:
+        case GET_REPORT_RESULTS:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         log.debug("Processing {}",

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java
new file mode 100644
index 0000000..3cacf39
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceReportResultsToListConverter.java
@@ -0,0 +1,515 @@
+/**
+ * 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.salesforce.api;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AbstractReportResultsBase;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AggregateColumnInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.AsyncReportResults;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.DetailColumnInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.GroupingColumnInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.GroupingInfo;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.GroupingValue;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportExtendedMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportFactWithDetails;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportMetadata;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportRow;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.ReportStatusEnum;
+import org.apache.camel.component.salesforce.api.dto.analytics.reports.SummaryValue;
+
+/**
+ * Salesforce report results to <code>List&lt;List&lt;String&gt;&gt;</code>converter.
+ */
+@Converter
+public final class SalesforceReportResultsToListConverter {
+
+    public static final String INCLUDE_DETAILS = "CamelSalesforceIncludeDetails";
+    public static final String INCLUDE_HEADERS = "CamelSalesforceIncludeHeaders";
+    public static final String INCLUDE_SUMMARY = "CamelSalesforceIncludeSummary";
+
+    private static final String ROW_COUNT = "RowCount";
+    private static final String EMPTY_VALUE = "";
+    private static final List<String> EMPTY_STRING_LIST = Collections.emptyList();
+
+    private SalesforceReportResultsToListConverter() {
+    }
+
+    @Converter
+    public static List<List<String>> convertToList(final AbstractReportResultsBase reportResults,
+                                                   final Exchange exchange) {
+
+        List<List<String>> results = null;
+        if (reportResults instanceof AsyncReportResults) {
+            AsyncReportResults asyncReportResults = (AsyncReportResults) reportResults;
+            final ReportStatusEnum status = asyncReportResults.getAttributes().getStatus();
+            // only successfully completed async report results have data rows
+            if (status != ReportStatusEnum.Success) {
+                throw new IllegalArgumentException("Invalid asynchronous report results status " + status);
+            }
+        }
+
+        switch (reportResults.getReportMetadata().getReportFormat()) {
+        case TABULAR:
+            results = convertTabularResults(reportResults, exchange);
+            break;
+        case SUMMARY:
+            results = convertSummaryResults(reportResults, exchange);
+            break;
+        case MATRIX:
+            results = convertMatrixResults(reportResults, exchange);
+            break;
+        default:
+            // ignore
+        }
+
+        return results;
+    }
+
+    private static List<List<String>> convertTabularResults(final AbstractReportResultsBase reportResults, final Exchange exchange) {
+
+        final ArrayList<List<String>> result = new ArrayList<List<String>>();
+
+        final ReportMetadata reportMetadata = reportResults.getReportMetadata();
+        final String[] detailColumns = reportMetadata.getDetailColumns();
+
+        final ReportExtendedMetadata reportExtendedMetadata = reportResults.getReportExtendedMetadata();
+        final ReportFactWithDetails factWithDetails = reportResults.getFactMap().get("T!T");
+
+        // include detail rows?
+        final String[] aggregates = reportMetadata.getAggregates();
+        if (reportResults.getHasDetailRows() && getOption(exchange, INCLUDE_DETAILS, Boolean.TRUE)) {
+
+            final int rowLength = detailColumns.length;
+
+            // include detail headers?
+            if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+
+                final List<String> headers = new ArrayList<String>(rowLength);
+                result.add(headers);
+
+                addColumnHeaders(headers, reportExtendedMetadata.getDetailColumnInfo(), detailColumns);
+            }
+
+            final ReportRow[] reportRows = factWithDetails.getRows();
+            result.ensureCapacity(result.size() + reportRows.length);
+            for (ReportRow reportRow : reportRows) {
+
+                final List<String> row = new ArrayList<String>(rowLength);
+                result.add(row);
+
+                addRowValues(row, reportRow.getDataCells());
+            }
+
+            // include summary values?
+            if (aggregates.length > 0 && getOption(exchange, INCLUDE_SUMMARY, Boolean.TRUE)) {
+
+                addSummaryRows(result, detailColumns, null, aggregates, factWithDetails.getAggregates());
+            }
+
+        } else if (aggregates.length > 0) {
+
+            final int rowLength = aggregates.length;
+
+            // include summary headers?
+            if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+
+                final List<String> headers = new ArrayList<String>(rowLength);
+                result.add(headers);
+
+                addColumnHeaders(headers, reportExtendedMetadata.getAggregateColumnInfo(), aggregates);
+            }
+
+            // add summary values
+            final List<String> row = new ArrayList<String>(rowLength);
+            result.add(row);
+            addRowValues(row, factWithDetails.getAggregates());
+        }
+
+        return result;
+    }
+
+    private static List<List<String>> convertSummaryResults(final AbstractReportResultsBase reportResults, Exchange exchange) {
+
+        final ArrayList<List<String>> result = new ArrayList<List<String>>();
+
+        final ReportMetadata reportMetadata = reportResults.getReportMetadata();
+        final ReportExtendedMetadata reportExtendedMetadata = reportResults.getReportExtendedMetadata();
+        final String[] aggregates = reportMetadata.getAggregates();
+
+        final boolean includeDetails = reportResults.getHasDetailRows()
+            && getOption(exchange, INCLUDE_DETAILS, Boolean.TRUE);
+        final boolean includeSummary = aggregates.length > 0 && getOption(exchange, INCLUDE_SUMMARY, Boolean.TRUE);
+
+        // column list, including grouping columns and details if required
+        final ArrayList<DetailColumnInfo> columnInfos = new ArrayList<DetailColumnInfo>();
+        final String[] columnNames = getResultColumns(columnInfos, reportMetadata, reportExtendedMetadata,
+            includeDetails, includeSummary);
+
+        // include detail headers?
+        if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+            addColumnHeaders(result, columnInfos);
+        }
+
+        // process down groups
+        for (GroupingValue groupingValue : reportResults.getGroupingsDown().getGroupings()) {
+            addSummaryGroupValues(result, reportResults, columnNames, groupingValue,
+                EMPTY_STRING_LIST, includeDetails, includeSummary);
+        }
+
+        // add grand total
+        if (includeSummary) {
+
+            final ReportFactWithDetails grandTotal = reportResults.getFactMap().get("T!T");
+
+            addSummaryValues(result, includeDetails, columnNames, EMPTY_STRING_LIST,
+                aggregates, grandTotal.getAggregates());
+        }
+
+        return result;
+    }
+
+    private static List<List<String>> convertMatrixResults(final AbstractReportResultsBase reportResults, Exchange exchange) {
+        final ArrayList<List<String>> result = new ArrayList<List<String>>();
+
+        final ReportMetadata reportMetadata = reportResults.getReportMetadata();
+        final ReportExtendedMetadata reportExtendedMetadata = reportResults.getReportExtendedMetadata();
+        final String[] aggregates = reportMetadata.getAggregates();
+
+        final boolean includeDetails = reportResults.getHasDetailRows()
+            && getOption(exchange, INCLUDE_DETAILS, Boolean.TRUE);
+        final boolean includeSummary = aggregates.length > 0 && getOption(exchange, INCLUDE_SUMMARY, Boolean.TRUE);
+
+        // column list, including grouping columns and details if required
+        final ArrayList<DetailColumnInfo> columnInfos = new ArrayList<DetailColumnInfo>();
+        final String[] columnNames = getResultColumns(columnInfos, reportMetadata, reportExtendedMetadata,
+            includeDetails, includeSummary);
+
+        // include detail headers?
+        if (getOption(exchange, INCLUDE_HEADERS, Boolean.TRUE)) {
+            addColumnHeaders(result, columnInfos);
+        }
+
+        // process down groups
+        final GroupingValue[] groupingsDown = reportResults.getGroupingsDown().getGroupings();
+        for (GroupingValue groupingValue : groupingsDown) {
+            addMatrixGroupValues(result, reportResults, columnNames, groupingValue,
+                EMPTY_STRING_LIST, includeDetails, includeSummary, EMPTY_VALUE, true);
+        }
+
+        // add grand total
+        if (includeSummary) {
+
+            final Map<String, ReportFactWithDetails> factMap = reportResults.getFactMap();
+
+            // first add summary for across groups
+            final List<String> downGroupsPrefix = new ArrayList<String>(
+                Collections.nCopies(groupingsDown.length, EMPTY_VALUE));
+
+            for (GroupingValue acrossGrouping : reportResults.getGroupingsAcross().getGroupings()) {
+                addAcrossGroupSummaryValues(result, reportMetadata,
+                    includeDetails, columnNames, factMap, downGroupsPrefix, acrossGrouping);
+            }
+
+            final ReportFactWithDetails grandTotal = factMap.get("T!T");
+            addSummaryValues(result, includeDetails, columnNames, EMPTY_STRING_LIST,
+                reportResults.getReportMetadata().getAggregates(), grandTotal.getAggregates());
+        }
+
+        return result;
+    }
+
+    private static void addAcrossGroupSummaryValues(ArrayList<List<String>> result, ReportMetadata reportMetadata,
+                                                    boolean includeDetails, String[] columnNames,
+                                                    Map<String, ReportFactWithDetails> factMap,
+                                                    List<String> downGroupsPrefix, GroupingValue acrossGrouping) {
+
+        final List<String> newDownGroupsPrefix = new ArrayList<String>(downGroupsPrefix);
+        newDownGroupsPrefix.add(acrossGrouping.getLabel());
+
+        addSummaryValues(result, includeDetails, columnNames, newDownGroupsPrefix,
+            reportMetadata.getAggregates(),
+            factMap.get("T!" + acrossGrouping.getKey()).getAggregates());
+
+        // process across subgroups
+        for (GroupingValue subGroup : acrossGrouping.getGroupings()) {
+            addAcrossGroupSummaryValues(result, reportMetadata, includeDetails, columnNames, factMap,
+                newDownGroupsPrefix, subGroup);
+        }
+    }
+
+    private static void addMatrixGroupValues(ArrayList<List<String>> result, AbstractReportResultsBase reportResults,
+                                             String[] columnNames, GroupingValue groupingValue,
+                                             List<String> rowPrefix, boolean includeDetails, boolean includeSummary,
+                                             String keyPrefix, boolean downGroup) {
+
+        final String groupKey = groupingValue.getKey();
+        final String newKeyPrefix = keyPrefix + groupKey;
+
+        // group values prefix
+        final List<String> newPrefix = new ArrayList<String>(rowPrefix);
+        newPrefix.add(groupingValue.getLabel());
+
+        final GroupingValue[] groupings = groupingValue.getGroupings();
+        // has subgroups?
+        if (groupings.length > 0) {
+
+            for (GroupingValue subGroup : groupings) {
+                addMatrixGroupValues(result, reportResults, columnNames, subGroup, newPrefix,
+                    includeDetails, includeSummary, newKeyPrefix + "_", downGroup);
+            }
+
+        // process across groupings?
+        } else if (downGroup) {
+
+            for (GroupingValue acrossGroup : reportResults.getGroupingsAcross().getGroupings()) {
+                addMatrixGroupValues(result, reportResults, columnNames, acrossGroup, newPrefix,
+                    includeDetails, includeSummary, newKeyPrefix + "!", false);
+            }
+
+        // add lowest level across group detail rows?
+        } else if (includeDetails) {
+
+            addDetailRows(result, newPrefix, reportResults.getFactMap().get(newKeyPrefix));
+
+        // add group columns only at lowest across level?
+        } else if (!includeSummary) {
+
+            result.add(newPrefix);
+
+        }
+
+        // add summary values for down group or lowest level across group
+        if (includeSummary) {
+
+            final String summaryKey = getGroupTotalKey(keyPrefix, downGroup, groupKey);
+
+            addSummaryValues(result, includeDetails, columnNames, newPrefix,
+                reportResults.getReportMetadata().getAggregates(),
+                reportResults.getFactMap().get(summaryKey).getAggregates());
+        }
+    }
+
+    private static String getGroupTotalKey(String keyPrefix, boolean downGroup, String key) {
+        if (downGroup) {
+            // keyPrefix has rows only
+            return keyPrefix + key + "!T";
+        } else {
+            // keyPrefix is of the form r(_r)*!(c_)*
+            return keyPrefix + key;
+        }
+    }
+
+    private static void addSummaryGroupValues(ArrayList<List<String>> result, AbstractReportResultsBase reportResults,
+                                              String[] columnNames, GroupingValue groupingValue,
+                                              List<String> rowPrefix, boolean includeDetails, boolean includeSummary) {
+
+        // get fact map at this level
+        final ReportFactWithDetails factWithDetails = reportResults.getFactMap().get(groupingValue.getKey() + "!T");
+
+        final List<String> newPrefix = new ArrayList<String>(rowPrefix);
+        newPrefix.add(groupingValue.getLabel());
+
+        // more groups?
+        final GroupingValue[] groupings = groupingValue.getGroupings();
+        if (groupings.length > 0) {
+
+            for (GroupingValue subGroup : groupings) {
+                addSummaryGroupValues(result, reportResults, columnNames, subGroup, newPrefix,
+                    includeDetails, includeSummary);
+            }
+
+        // add lowest level group detail rows?
+        } else if (includeDetails) {
+
+            addDetailRows(result, newPrefix, factWithDetails);
+
+            // add group columns only at lowest level?
+        } else if (!includeSummary) {
+            result.add(newPrefix);
+        }
+
+        if (includeSummary) {
+            final SummaryValue[] summaryValues = factWithDetails.getAggregates();
+            final String[] aggregates = reportResults.getReportMetadata().getAggregates();
+
+            addSummaryValues(result, includeDetails, columnNames, newPrefix, aggregates, summaryValues);
+        }
+    }
+
+    private static void addDetailRows(ArrayList<List<String>> result, List<String> newPrefix, ReportFactWithDetails factWithDetails) {
+        final ReportRow[] rows = factWithDetails.getRows();
+        result.ensureCapacity(result.size() + rows.length);
+        for (ReportRow row : rows) {
+            final ArrayList<String> rowValues = new ArrayList<String>(newPrefix);
+            addRowValues(rowValues, row.getDataCells());
+            result.add(rowValues);
+        }
+    }
+
+    private static void addSummaryValues(ArrayList<List<String>> result, boolean includeDetails,
+                                         String[] columnNames, List<String> newPrefix,
+                                         String[] aggregates, SummaryValue[] summaryValues) {
+        // no summary values to add
+        if (summaryValues.length == 0) {
+            return;
+        }
+
+        if (includeDetails) {
+            // add summary rows for this group
+            addSummaryRows(result, columnNames, newPrefix,
+                aggregates, summaryValues);
+        } else {
+            // add summary values as columns for this group
+            final ArrayList<String> summaryRow = new ArrayList<String>(newPrefix);
+            // add remaining group values
+            final int nGroups = columnNames.length - summaryValues.length;
+            for (int i = summaryRow.size(); i < nGroups; i++) {
+                summaryRow.add(EMPTY_VALUE);
+            }
+            addRowValues(summaryRow, summaryValues);
+            result.add(summaryRow);
+        }
+    }
+
+    private static void addSummaryRows(List<List<String>> result,
+                                       String[] detailColumns, List<String> rowPrefix,
+                                       String[] aggregateColumns, SummaryValue[] summaryValues) {
+
+        final ArrayList<List<String>> rows = new ArrayList<List<String>>(summaryValues.length + 1);
+        String rowCount = null;
+        for (int i = 0; i < aggregateColumns.length; i++) {
+
+            final String aggregate = aggregateColumns[i];
+
+            final String valueLabel = summaryValues[i].getLabel();
+            if (ROW_COUNT.equals(aggregate)) {
+                rowCount = valueLabel;
+            } else {
+
+                final List<String> summaryRow = rowPrefix == null
+                    ? new ArrayList<String>() : new ArrayList<String>(rowPrefix);
+                rows.add(summaryRow);
+
+                // skip rowPrefix columns if not null
+                for (int j = rowPrefix == null ? 0 : rowPrefix.size(); j < detailColumns.length; j++) {
+
+                    final String columnName = detailColumns[j];
+                    if (aggregate.endsWith("!" + columnName)) {
+                        final StringBuilder valueBuilder = new StringBuilder();
+                        if (aggregate.startsWith("a!")) {
+                            valueBuilder.append("avg ");
+                        } else if (aggregate.startsWith("mx!")) {
+                            valueBuilder.append("max ");
+                        } else if (aggregate.startsWith("m!")) {
+                            valueBuilder.append("min ");
+                        }
+                        valueBuilder.append(valueLabel);
+                        summaryRow.add(valueBuilder.toString());
+                    } else {
+                        summaryRow.add(EMPTY_VALUE);
+                    }
+                }
+            }
+        }
+
+        // add a Grand Totals separator row
+        final List<String> grandTotal = new ArrayList<String>();
+        result.add(grandTotal);
+
+        if (rowCount != null) {
+            grandTotal.add("Grand Totals (" +  rowCount + " records)");
+        } else {
+            grandTotal.add("Grand Totals");
+        }
+
+        // add summary values rows
+        result.addAll(rows);
+    }
+
+    private static String[] getResultColumns(List<DetailColumnInfo> result, ReportMetadata reportMetadata,
+                                                       ReportExtendedMetadata reportExtendedMetadata,
+                                                       boolean includeDetails, boolean includeSummary) {
+
+        final List<String> columnNames = new ArrayList<String>();
+
+        // add grouping columns before detail columns
+        final Map<String, GroupingColumnInfo> groupingColumnInfos = reportExtendedMetadata.getGroupingColumnInfo();
+        for (GroupingInfo downGroup : reportMetadata.getGroupingsDown()) {
+            final String name = downGroup.getName();
+            columnNames.add(name);
+            result.add(groupingColumnInfos.get(name));
+        }
+        for (GroupingInfo acrossGroup : reportMetadata.getGroupingsAcross()) {
+            final String name = acrossGroup.getName();
+            columnNames.add(name);
+            result.add(groupingColumnInfos.get(name));
+        }
+
+        // include details?
+        if (!includeDetails) {
+            // include summary columns?
+            if (includeSummary) {
+                final Map<String, AggregateColumnInfo> aggregateColumnInfos =
+                    reportExtendedMetadata.getAggregateColumnInfo();
+                for (String aggregateColumnName : reportMetadata.getAggregates()) {
+                    columnNames.add(aggregateColumnName);
+                    result.add(aggregateColumnInfos.get(aggregateColumnName));
+                }
+            }
+        } else {
+            // add detail columns
+            final Map<String, DetailColumnInfo> detailColumnInfo = reportExtendedMetadata.getDetailColumnInfo();
+            for (String columnName : reportMetadata.getDetailColumns()) {
+                columnNames.add(columnName);
+                result.add(detailColumnInfo.get(columnName));
+            }
+        }
+
+        return columnNames.toArray(new String[columnNames.size()]);
+    }
+
+    private static void addColumnHeaders(List<String> headers,
+                                         Map<String, ? extends DetailColumnInfo> columnInfos, String[] columns) {
+        for (String columnName : columns) {
+            headers.add(columnInfos.get(columnName).getLabel());
+        }
+    }
+
+    private static void addColumnHeaders(List<List<String>> result, ArrayList<DetailColumnInfo> columnInfos) {
+        final ArrayList<String> headers = new ArrayList<String>(columnInfos.size());
+        for (DetailColumnInfo info : columnInfos) {
+            headers.add(info.getLabel());
+        }
+        result.add(headers);
+    }
+
+    private static void addRowValues(List<String> row, SummaryValue[] values) {
+        for (SummaryValue summaryValue : values) {
+            row.add(summaryValue.getLabel());
+        }
+    }
+
+    private static boolean getOption(Exchange exchange, String name, Boolean defaultValue) {
+        return exchange.getIn().getHeader(name, defaultValue, Boolean.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
index 2ae2cfd..4e69738 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/PickListValue.java
@@ -19,7 +19,7 @@ package org.apache.camel.component.salesforce.api.dto;
 /**
  * Salesforce DTO for picklist value.
  */
-public class PickListValue {
+public class PickListValue extends AbstractDTOBase {
 
     private String value;
     private String label;

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
index b37aa13..a07cb6a 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/RestResources.java
@@ -45,6 +45,7 @@ public class RestResources extends AbstractDTOBase {
     private String compactLayouts;
     private String actions;
     private String tabs;
+    private String wave;
 
     public String getSobjects() {
         return sobjects;
@@ -213,4 +214,12 @@ public class RestResources extends AbstractDTOBase {
     public void setTabs(String tabs) {
         this.tabs = tabs;
     }
+
+    public String getWave() {
+        return wave;
+    }
+
+    public void setWave(String wave) {
+        this.wave = wave;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
index 312e6c3..967064f 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/SObjectField.java
@@ -74,6 +74,7 @@ public class SObjectField extends AbstractDTOBase {
     private String maskType;
     private Boolean queryByDistance;
     private String referenceTargetField;
+    private Boolean encrypted;
 
     public Integer getLength() {
         return length;
@@ -474,4 +475,12 @@ public class SObjectField extends AbstractDTOBase {
     public void setReferenceTargetField(String referenceTargetField) {
         this.referenceTargetField = referenceTargetField;
     }
+
+    public Boolean getEncrypted() {
+        return encrypted;
+    }
+
+    public void setEncrypted(Boolean encrypted) {
+        this.encrypted = encrypted;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java
new file mode 100644
index 0000000..90de38b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractAttributesBase.java
@@ -0,0 +1,53 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Base DTO for report attributes.
+ */
+public abstract class AbstractAttributesBase extends AbstractDTOBase {
+
+    private String type;
+    private String reportName;
+    private String reportId;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getReportName() {
+        return reportName;
+    }
+
+    public void setReportName(String reportName) {
+        this.reportName = reportName;
+    }
+
+    public String getReportId() {
+        return reportId;
+    }
+
+    public void setReportId(String reportId) {
+        this.reportId = reportId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java
new file mode 100644
index 0000000..8d0f475
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AbstractReportResultsBase.java
@@ -0,0 +1,91 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Base DTO for report results.
+ */
+public abstract class AbstractReportResultsBase extends AbstractDTOBase {
+
+    private Boolean hasDetailRows;
+    private ReportMetadata reportMetadata;
+    private ReportExtendedMetadata reportExtendedMetadata;
+    private Groupings groupingsDown;
+    private Groupings groupingsAcross;
+    private Boolean allData;
+    private Map<String, ReportFactWithDetails> factMap;
+
+    public Boolean getHasDetailRows() {
+        return hasDetailRows;
+    }
+
+    public void setHasDetailRows(Boolean hasDetailRows) {
+        this.hasDetailRows = hasDetailRows;
+    }
+
+    public ReportMetadata getReportMetadata() {
+        return reportMetadata;
+    }
+
+    public void setReportMetadata(ReportMetadata reportMetadata) {
+        this.reportMetadata = reportMetadata;
+    }
+
+    public ReportExtendedMetadata getReportExtendedMetadata() {
+        return reportExtendedMetadata;
+    }
+
+    public void setReportExtendedMetadata(ReportExtendedMetadata reportExtendedMetadata) {
+        this.reportExtendedMetadata = reportExtendedMetadata;
+    }
+
+    public Groupings getGroupingsDown() {
+        return groupingsDown;
+    }
+
+    public void setGroupingsDown(Groupings groupingsDown) {
+        this.groupingsDown = groupingsDown;
+    }
+
+    public Groupings getGroupingsAcross() {
+        return groupingsAcross;
+    }
+
+    public void setGroupingsAcross(Groupings groupingsAcross) {
+        this.groupingsAcross = groupingsAcross;
+    }
+
+    public Boolean getAllData() {
+        return allData;
+    }
+
+    public void setAllData(Boolean allData) {
+        this.allData = allData;
+    }
+
+    public Map<String, ReportFactWithDetails> getFactMap() {
+        return factMap;
+    }
+
+    public void setFactMap(Map<String, ReportFactWithDetails> factMap) {
+        this.factMap = factMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.java
new file mode 100644
index 0000000..766ec9e
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AggregateColumnInfo.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.component.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report results aggregate column info.
+ */
+public class AggregateColumnInfo extends DetailColumnInfo {
+
+    private String acrossGroupingContext;
+    private String downGroupingContext;
+
+    public String getAcrossGroupingContext() {
+        return acrossGroupingContext;
+    }
+
+    public void setAcrossGroupingContext(String acrossGroupingContext) {
+        this.acrossGroupingContext = acrossGroupingContext;
+    }
+
+    public String getDownGroupingContext() {
+        return downGroupingContext;
+    }
+
+    public void setDownGroupingContext(String downGroupingContext) {
+        this.downGroupingContext = downGroupingContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java
new file mode 100644
index 0000000..d66583a
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncAttributes.java
@@ -0,0 +1,71 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.joda.time.DateTime;
+
+/**
+ * Async report attributes DTO.
+ */
+public class AsyncAttributes extends AbstractAttributesBase {
+
+    private String id;
+    private ReportStatusEnum status;
+    private String ownerId;
+    private DateTime completionDate;
+    private DateTime requestDate;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public ReportStatusEnum getStatus() {
+        return status;
+    }
+
+    public void setStatus(ReportStatusEnum status) {
+        this.status = status;
+    }
+
+    public String getOwnerId() {
+        return ownerId;
+    }
+
+    public void setOwnerId(String ownerId) {
+        this.ownerId = ownerId;
+    }
+
+    public DateTime getCompletionDate() {
+        return completionDate;
+    }
+
+    public void setCompletionDate(DateTime completionDate) {
+        this.completionDate = completionDate;
+    }
+
+    public DateTime getRequestDate() {
+        return requestDate;
+    }
+
+    public void setRequestDate(DateTime requestDate) {
+        this.requestDate = requestDate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java
new file mode 100644
index 0000000..e341fe4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/AsyncReportResults.java
@@ -0,0 +1,33 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Sync Report results DTO.
+ */
+public class AsyncReportResults extends AbstractReportResultsBase {
+
+    private AsyncAttributes attributes;
+
+    public AsyncAttributes getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(AsyncAttributes attributes) {
+        this.attributes = attributes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java
new file mode 100644
index 0000000..08d9062
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ColumnSortOrderEnum.java
@@ -0,0 +1,24 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Grouping column sort order.
+ */
+public enum ColumnSortOrderEnum {
+    Asc, Desc
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java
new file mode 100644
index 0000000..56e8702
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DateGranularityEnum.java
@@ -0,0 +1,73 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonValue;
+
+/**
+ * Report results groupings date granularity.
+ */
+public enum DateGranularityEnum {
+
+    // None
+    NONE("None"),
+    // Day
+    DAY("Day"),
+    // Calendar Week
+    CALENDAR_WEEK("Calendar Week"),
+    // Calendar Month
+    CALENDAR_MONTH("Calendar Month"),
+    // Calendar Quarter
+    CALENDAR_QUARTER("Calendar Quarter"),
+    // Calendar Year
+    CALENDAR_YEAR("Calendar Year"),
+    // Calendar Month in Year
+    CALENDAR_MONTH_IN_YEAR("Calendar Month in Year"),
+    // Calendar Day in Month
+    CALENDAR_DAY_IN_MONTH("Calendar Day in Month"),
+    // Fiscal Period
+    FISCAL_PERIOD("Fiscal Period"),
+    // Fiscal Week
+    FISCAL_WEEK("Fiscal Week"),
+    // Fiscal Quarter
+    FISCAL_QUARTER("Fiscal Quarter"),
+    // Fiscal Year
+    FISCAL_YEAR("Fiscal Year");
+
+    private final String value;
+
+    DateGranularityEnum(String value) {
+        this.value = value;
+    }
+
+    @JsonValue
+    public String value() {
+        return value;
+    }
+
+    @JsonCreator
+    public static DateGranularityEnum fromValue(String value) {
+        for (DateGranularityEnum e : DateGranularityEnum.values()) {
+            if (e.value.equals(value)) {
+                return e;
+            }
+        }
+        throw new IllegalArgumentException(value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java
new file mode 100644
index 0000000..8c3b316
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/DetailColumnInfo.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results details column info.
+ */
+public class DetailColumnInfo extends AbstractDTOBase {
+
+    private String label;
+    private String dataType;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java
new file mode 100644
index 0000000..7358662
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterOperator.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type metadata filter operator reference.
+ */
+public class FilterOperator extends AbstractDTOBase {
+
+    private String name;
+    private String label;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java
new file mode 100644
index 0000000..d5298c4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FilterValue.java
@@ -0,0 +1,44 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report type column filter value.
+ */
+public class FilterValue extends AbstractDTOBase {
+
+    private String label;
+    private String name;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java
new file mode 100644
index 0000000..b9b825b
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/FormatEnum.java
@@ -0,0 +1,57 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonValue;
+
+/**
+ * Salesforce Enumeration DTO for picklist Format
+ */
+public enum FormatEnum {
+
+    // Matrix
+    MATRIX("Matrix"),
+    // MultiBlock
+    MULTIBLOCK("MultiBlock"),
+    // Summary
+    SUMMARY("Summary"),
+    // Tabular
+    TABULAR("Tabular");
+
+    final String value;
+
+    private FormatEnum(String value) {
+        this.value = value;
+    }
+
+    @JsonValue
+    public String value() {
+        return this.value;
+    }
+
+    @JsonCreator
+    public static FormatEnum fromValue(String value) {
+        for (FormatEnum e : FormatEnum.values()) {
+            if (e.value.equals(value)) {
+                return e;
+            }
+        }
+        throw new IllegalArgumentException(value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java
new file mode 100644
index 0000000..21c3142
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingColumnInfo.java
@@ -0,0 +1,33 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+/**
+ * Report results grouping column info.
+ */
+public class GroupingColumnInfo extends DetailColumnInfo {
+
+    private Integer groupingLevel;
+
+    public Integer getGroupingLevel() {
+        return groupingLevel;
+    }
+
+    public void setGroupingLevel(Integer groupingLevel) {
+        this.groupingLevel = groupingLevel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java
new file mode 100644
index 0000000..08588bf
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingInfo.java
@@ -0,0 +1,62 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report metadata grouping info.
+ */
+public class GroupingInfo extends AbstractDTOBase {
+
+    private String name;
+    private String sortAggregate;
+    private ColumnSortOrderEnum sortOrder;
+    private DateGranularityEnum dateGranularity;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSortAggregate() {
+        return sortAggregate;
+    }
+
+    public void setSortAggregate(String sortAggregate) {
+        this.sortAggregate = sortAggregate;
+    }
+
+    public ColumnSortOrderEnum getSortOrder() {
+        return sortOrder;
+    }
+
+    public void setSortOrder(ColumnSortOrderEnum sortOrder) {
+        this.sortOrder = sortOrder;
+    }
+
+    public DateGranularityEnum getDateGranularity() {
+        return dateGranularity;
+    }
+
+    public void setDateGranularity(DateGranularityEnum dateGranularity) {
+        this.dateGranularity = dateGranularity;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java
new file mode 100644
index 0000000..b27e3d4
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/GroupingValue.java
@@ -0,0 +1,72 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results grouping value.
+ */
+public class GroupingValue extends AbstractDTOBase {
+
+    private String value;
+    private String key;
+    private String label;
+    private GroupingValue[] groupings;
+    // TODO the description is vague about this!!!
+    private GroupingValue[] dategroupings;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public GroupingValue[] getGroupings() {
+        return groupings;
+    }
+
+    public void setGroupings(GroupingValue[] groupings) {
+        this.groupings = groupings;
+    }
+
+    public GroupingValue[] getDategroupings() {
+        return dategroupings;
+    }
+
+    public void setDategroupings(GroupingValue[] dategroupings) {
+        this.dategroupings = dategroupings;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java
new file mode 100644
index 0000000..0bb8af1
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Groupings.java
@@ -0,0 +1,35 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report results groupings.
+ */
+public class Groupings extends AbstractDTOBase {
+
+    private GroupingValue[] groupings;
+
+    public GroupingValue[] getGroupings() {
+        return groupings;
+    }
+
+    public void setGroupings(GroupingValue[] groupings) {
+        this.groupings = groupings;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java
new file mode 100644
index 0000000..3e276f1
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/QueryRecordsReport.java
@@ -0,0 +1,40 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import java.util.List;
+
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractQueryRecordsBase;
+
+/**
+ * Salesforce QueryRecords DTO for type Report
+ */
+public class QueryRecordsReport extends AbstractQueryRecordsBase {
+
+    @XStreamImplicit
+    private List<Report> records;
+
+    public List<Report> getRecords() {
+        return records;
+    }
+
+    public void setRecords(List<Report> records) {
+        this.records = records;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java
new file mode 100644
index 0000000..547b0a7
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/RecentReport.java
@@ -0,0 +1,71 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report list info DTO.
+ */
+public class RecentReport extends AbstractDTOBase {
+
+    private String name;
+    private String id;
+    private String url;
+    private String describeUrl;
+    private String instancesUrl;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getDescribeUrl() {
+        return describeUrl;
+    }
+
+    public void setDescribeUrl(String describeUrl) {
+        this.describeUrl = describeUrl;
+    }
+
+    public String getInstancesUrl() {
+        return instancesUrl;
+    }
+
+    public void setInstancesUrl(String instancesUrl) {
+        this.instancesUrl = instancesUrl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java
new file mode 100644
index 0000000..452480a
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/Report.java
@@ -0,0 +1,100 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamConverter;
+
+import org.apache.camel.component.salesforce.api.PicklistEnumConverter;
+import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Salesforce DTO for SObject Report
+ */
+//CHECKSTYLE:OFF
+@XStreamAlias("Report")
+public class Report extends AbstractSObjectBase {
+
+    // Description
+    private String Description;
+
+    // DeveloperName
+    private String DeveloperName;
+
+    // NamespacePrefix
+    private String NamespacePrefix;
+
+    // LastRunDate
+    private org.joda.time.DateTime LastRunDate;
+
+    // Format
+    @XStreamConverter(PicklistEnumConverter.class)
+    private FormatEnum Format;
+
+    @JsonProperty("Description")
+    public String getDescription() {
+        return this.Description;
+    }
+
+    @JsonProperty("Description")
+    public void setDescription(String Description) {
+        this.Description = Description;
+    }
+
+    @JsonProperty("DeveloperName")
+    public String getDeveloperName() {
+        return this.DeveloperName;
+    }
+
+    @JsonProperty("DeveloperName")
+    public void setDeveloperName(String DeveloperName) {
+        this.DeveloperName = DeveloperName;
+    }
+
+    @JsonProperty("NamespacePrefix")
+    public String getNamespacePrefix() {
+        return this.NamespacePrefix;
+    }
+
+    @JsonProperty("NamespacePrefix")
+    public void setNamespacePrefix(String NamespacePrefix) {
+        this.NamespacePrefix = NamespacePrefix;
+    }
+
+    @JsonProperty("LastRunDate")
+    public org.joda.time.DateTime getLastRunDate() {
+        return this.LastRunDate;
+    }
+
+    @JsonProperty("LastRunDate")
+    public void setLastRunDate(org.joda.time.DateTime LastRunDate) {
+        this.LastRunDate = LastRunDate;
+    }
+
+    @JsonProperty("Format")
+    public FormatEnum getFormat() {
+        return this.Format;
+    }
+
+    @JsonProperty("Format")
+    public void setFormat(FormatEnum Format) {
+        this.Format = Format;
+    }
+
+}
+//CHECKSTYLE:ON

http://git-wip-us.apache.org/repos/asf/camel/blob/b508c4dc/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java
new file mode 100644
index 0000000..a7c7e60
--- /dev/null
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/analytics/reports/ReportDescription.java
@@ -0,0 +1,53 @@
+/**
+ * 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.salesforce.api.dto.analytics.reports;
+
+import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase;
+
+/**
+ * Report description DTO.
+ */
+public class ReportDescription extends AbstractDTOBase {
+
+    private ReportTypeMetadata reportTypeMetadata;
+    private ReportExtendedMetadata reportExtendedMetadata;
+    private ReportMetadata reportMetadata;
+
+    public ReportTypeMetadata getReportTypeMetadata() {
+        return reportTypeMetadata;
+    }
+
+    public void setReportTypeMetadata(ReportTypeMetadata reportTypeMetadata) {
+        this.reportTypeMetadata = reportTypeMetadata;
+    }
+
+    public ReportExtendedMetadata getReportExtendedMetadata() {
+        return reportExtendedMetadata;
+    }
+
+    public void setReportExtendedMetadata(ReportExtendedMetadata reportExtendedMetadata) {
+        this.reportExtendedMetadata = reportExtendedMetadata;
+    }
+
+    public ReportMetadata getReportMetadata() {
+        return reportMetadata;
+    }
+
+    public void setReportMetadata(ReportMetadata reportMetadata) {
+        this.reportMetadata = reportMetadata;
+    }
+}