You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2018/06/25 10:45:22 UTC

[camel] 01/02: CAMEL-12578: camel-servicenow: add metadata option to list available tables

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

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

commit b498e8180a7d2cc2fd40f58578ab1827fcdde9d4
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Mon Jun 25 12:22:26 2018 +0200

    CAMEL-12578: camel-servicenow: add metadata option to list available tables
---
 .../servicenow/ServiceNowMetaDataExtension.java    | 300 +++++++++++++--------
 .../ServiceNowMetaDataExtensionTest.java           |   2 +
 2 files changed, 193 insertions(+), 109 deletions(-)

diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
index 1160f26..6f3f5de 100644
--- a/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
+++ b/components/camel-servicenow/camel-servicenow-component/src/main/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtension.java
@@ -39,6 +39,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.component.extension.MetaDataExtension;
 import org.apache.camel.component.extension.metadata.AbstractMetaDataExtension;
@@ -60,101 +61,189 @@ final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
     private final ConcurrentMap<String, String> properties;
 
     ServiceNowMetaDataExtension() {
+        this(null);
+    }
+
+    ServiceNowMetaDataExtension(CamelContext context) {
+        super(context);
+
         this.properties = new ConcurrentHashMap<>();
     }
 
     @Override
-    public Optional<MetaDataExtension.MetaData> meta(Map<String, Object> parameters) {
+    public Optional<MetaData> meta(Map<String, Object> parameters) {
         final String objectType = (String)parameters.get("objectType");
+        final String metaType = (String)parameters.getOrDefault("metaType", "definition");
 
-        if (ObjectHelper.equalIgnoreCase(objectType, ServiceNowConstants.RESOURCE_TABLE)) {
+        // Retrieve the table definition as json-scheme
+        if (ObjectHelper.equalIgnoreCase(objectType, ServiceNowConstants.RESOURCE_TABLE) && ObjectHelper.equalIgnoreCase(metaType, "definition")) {
             final MetaContext context = new MetaContext(parameters);
 
             // validate meta parameters
             ObjectHelper.notNull(context.getObjectType(), "objectType");
             ObjectHelper.notNull(context.getObjectName(), "objectName");
 
-            return tableMeta(context);
+            try {
+                return tableDefinition(context);
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        // retrieve the list of tables excluding those used for import sets
+        if (ObjectHelper.equalIgnoreCase(objectType, ServiceNowConstants.RESOURCE_TABLE) && ObjectHelper.equalIgnoreCase(metaType, "list")) {
+            final MetaContext context = new MetaContext(parameters);
+
+            // validate meta parameters
+            ObjectHelper.notNull(context.getObjectType(), "objectType");
+
+            try {
+                return tableList(context);
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
+            }
         }
 
-        if (ObjectHelper.equalIgnoreCase(objectType, ServiceNowConstants.RESOURCE_IMPORT)) {
+        // retrieve the list of import set tables
+        if (ObjectHelper.equalIgnoreCase(objectType, ServiceNowConstants.RESOURCE_IMPORT) && ObjectHelper.equalIgnoreCase(metaType, "list")) {
             final MetaContext context = new MetaContext(parameters);
 
             // validate mate parameters
             ObjectHelper.notNull(context.getObjectType(), "objectType");
 
-            return importSetMeta(context);
+            try {
+                return importSetList(context);
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
+            }
         }
 
         throw new UnsupportedOperationException("Unsupported object type <" + objectType + ">");
     }
 
-    private Optional<MetaDataExtension.MetaData> tableMeta(MetaContext context) {
-        try {
-            final List<String> names = getObjectHierarchy(context);
-            final ObjectNode root = context.getConfiguration().getOrCreateMapper().createObjectNode();
-            final String baseUrn = (String)context.getParameters().getOrDefault("baseUrn", "org:apache:camel:component:servicenow");
+    private Optional<MetaData> tableDefinition(MetaContext context) throws Exception {
+        final List<String> names = getObjectHierarchy(context);
+        final ObjectNode root = context.getConfiguration().getOrCreateMapper().createObjectNode();
+        final String baseUrn = (String)context.getParameters().getOrDefault("baseUrn", "org:apache:camel:component:servicenow");
 
-            // Schema
-            root.put("$schema", "http://json-schema.org/schema#");
-            root.put("id", String.format("urn:jsonschema:%s:%s)", baseUrn, context.getObjectName()));
-            root.put("type", "object");
-            root.put("additionalProperties", false);
+        // Schema
+        root.put("$schema", "http://json-schema.org/schema#");
+        root.put("id", String.format("urn:jsonschema:%s:%s)", baseUrn, context.getObjectName()));
+        root.put("type", "object");
+        root.put("additionalProperties", false);
 
-            // Schema sections
-            root.putObject("properties");
-            root.putArray("required");
+        // Schema sections
+        root.putObject("properties");
+        root.putArray("required");
 
-            loadProperties(context);
+        loadProperties(context);
 
-            for (String name : names) {
-                context.getStack().push(name);
+        for (String name : names) {
+            context.getStack().push(name);
 
-                LOGGER.debug("Load dictionary <{}>", context.getStack());
-                loadDictionary(context, name, root);
-                context.getStack().pop();
-            }
-
-            final String dateFormat = properties.getOrDefault("glide.sys.date_format", "yyyy-MM-dd");
-            final String timeFormat = properties.getOrDefault("glide.sys.time_format", "HH:mm:ss");
-
-            return Optional.of(
-                MetaDataBuilder.on(getCamelContext())
-                    .withAttribute(MetaData.CONTENT_TYPE, "application/schema+json")
-                    .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
-                    .withAttribute(MetaData.CONTEXT, ServiceNowConstants.RESOURCE_TABLE)
-                    .withAttribute("date.format", dateFormat)
-                    .withAttribute("time.format", timeFormat)
-                    .withAttribute("date-time.format", dateFormat + " " + timeFormat)
-                    .withPayload(root)
-                    .build()
-            );
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+            LOGGER.debug("Load dictionary <{}>", context.getStack());
+            loadDictionary(context, name, root);
+            context.getStack().pop();
         }
+
+        final String dateFormat = properties.getOrDefault("glide.sys.date_format", "yyyy-MM-dd");
+        final String timeFormat = properties.getOrDefault("glide.sys.time_format", "HH:mm:ss");
+
+        return Optional.of(
+            MetaDataBuilder.on(getCamelContext())
+                .withAttribute(MetaData.CONTENT_TYPE, "application/schema+json")
+                .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
+                .withAttribute("date.format", dateFormat)
+                .withAttribute("time.format", timeFormat)
+                .withAttribute("date-time.format", dateFormat + " " + timeFormat)
+                .withPayload(root)
+                .build()
+        );
     }
 
-    private Optional<MetaDataExtension.MetaData> importSetMeta(MetaContext context) {
-        try {
-            Optional<JsonNode> response = context.getClient().reset()
+    private Optional<MetaData> importSetList(MetaContext context) throws Exception {
+        Optional<JsonNode> response = context.getClient().reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(context.getConfiguration().getApiVersion())
+            .path("table")
+            .path("sys_db_object")
+            .query("sysparm_exclude_reference_link", "true")
+            .query("sysparm_fields", "name%2Csys_id")
+            .query("sysparm_query", "name=sys_import_set_row")
+            .trasform(HttpMethod.GET, this::findResultNode);
+
+        if (response.isPresent()) {
+            final JsonNode node = response.get();
+            final JsonNode sysId = node.findValue("sys_id");
+
+            if (sysId == null) {
+                throw new IllegalStateException("Unable to determine sys_id of sys_import_set_row");
+            }
+
+            response = context.getClient().reset()
                 .types(MediaType.APPLICATION_JSON_TYPE)
                 .path("now")
                 .path(context.getConfiguration().getApiVersion())
                 .path("table")
                 .path("sys_db_object")
                 .query("sysparm_exclude_reference_link", "true")
-                .query("sysparm_fields", "name%2Csys_id")
-                .query("sysparm_query", "name=sys_import_set_row")
+                .query("sysparm_fields", "name%2Csys_name")
+                .queryF("sysparm_query", "super_class=%s", sysId.textValue())
                 .trasform(HttpMethod.GET, this::findResultNode);
 
             if (response.isPresent()) {
-                final JsonNode node = response.get();
-                final JsonNode sysId = node.findValue("sys_id");
+                final ObjectNode root = context.getConfiguration().getOrCreateMapper().createObjectNode();
 
-                if (sysId == null) {
-                    throw new RuntimeException("Unable to determine sys_id of sys_import_set_row");
-                }
+                processResult(response.get(), n -> {
+                    final JsonNode name = n.findValue("name");
+                    final JsonNode label = n.findValue("sys_name");
 
+                    if (name != null && label != null) {
+                        root.put(name.textValue(), label.textValue());
+                    }
+                });
+
+                return Optional.of(
+                    MetaDataBuilder.on(getCamelContext())
+                        .withAttribute(MetaData.CONTENT_TYPE, "application/json")
+                        .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
+                        .withPayload(root)
+                        .build()
+                );
+            }
+        }
+
+        return Optional.empty();
+    }
+
+    private Optional<MetaData> tableList(MetaContext context) throws Exception {
+        Optional<JsonNode> response = context.getClient().reset()
+            .types(MediaType.APPLICATION_JSON_TYPE)
+            .path("now")
+            .path(context.getConfiguration().getApiVersion())
+            .path("table")
+            .path("sys_db_object")
+            .query("sysparm_exclude_reference_link", "true")
+            .query("sysparm_fields", "name%2Csys_id")
+            .query("sysparm_query", "name=sys_import_set_row")
+            .trasform(HttpMethod.GET, this::findResultNode);
+
+        if (response.isPresent()) {
+            final JsonNode node = response.get();
+            final JsonNode sysId = node.findValue("sys_id");
+
+            if (sysId == null) {
+                response = context.getClient().reset()
+                    .types(MediaType.APPLICATION_JSON_TYPE)
+                    .path("now")
+                    .path(context.getConfiguration().getApiVersion())
+                    .path("table")
+                    .path("sys_db_object")
+                    .query("sysparm_exclude_reference_link", "true")
+                    .query("sysparm_fields", "name%2Csys_name")
+                    .trasform(HttpMethod.GET, this::findResultNode);
+            } else {
                 response = context.getClient().reset()
                     .types(MediaType.APPLICATION_JSON_TYPE)
                     .path("now")
@@ -163,33 +252,31 @@ final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
                     .path("sys_db_object")
                     .query("sysparm_exclude_reference_link", "true")
                     .query("sysparm_fields", "name%2Csys_name")
-                    .queryF("sysparm_query", "super_class=%s", sysId.textValue())
+                    .queryF("sysparm_query", "super_class!=%s", sysId.textValue())
                     .trasform(HttpMethod.GET, this::findResultNode);
+            }
 
-                if (response.isPresent()) {
-                    final ObjectNode root = context.getConfiguration().getOrCreateMapper().createObjectNode();
+            if (response.isPresent()) {
+                final ObjectNode root = context.getConfiguration().getOrCreateMapper().createObjectNode();
 
-                    processResult(response.get(), n -> {
-                        final JsonNode name = n.findValue("name");
-                        final JsonNode label = n.findValue("sys_name");
+                processResult(response.get(), n -> {
+                    final JsonNode name = n.findValue("name");
+                    final JsonNode label = n.findValue("sys_name");
 
-                        if (name != null && label != null) {
-                            root.put(name.textValue(), label.textValue());
-                        }
-                    });
-
-                    return Optional.of(
-                        MetaDataBuilder.on(getCamelContext())
-                            .withAttribute(MetaData.CONTENT_TYPE, "application/json")
-                            .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
-                            .withAttribute(MetaData.CONTEXT, ServiceNowConstants.RESOURCE_IMPORT)
-                            .withPayload(root)
-                            .build()
-                    );
-                }
+                    if (name != null && label != null) {
+                        root.put(name.textValue(), label.textValue());
+                    }
+                });
+
+                return Optional.of(
+                    MetaDataBuilder.on(getCamelContext())
+                        .withAttribute(MetaData.CONTENT_TYPE, "application/json")
+                        .withAttribute(MetaData.JAVA_TYPE, JsonNode.class)
+                        .withAttribute("Meta-Context", ServiceNowConstants.RESOURCE_IMPORT)
+                        .withPayload(root)
+                        .build()
+                );
             }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
         }
 
         return Optional.empty();
@@ -199,45 +286,41 @@ final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
     // Properties
     // ********************************
 
-    private synchronized void loadProperties(MetaContext context) {
+    private void loadProperties(MetaContext context) throws Exception {
         if (!properties.isEmpty()) {
             return;
         }
 
-        try {
-            String offset = "0";
+        String offset = "0";
 
-            while (true) {
-                Response response = context.getClient().reset()
-                    .types(MediaType.APPLICATION_JSON_TYPE)
-                    .path("now")
-                    .path(context.getConfiguration().getApiVersion())
-                    .path("table")
-                    .path("sys_properties")
-                    .query("sysparm_exclude_reference_link", "true")
-                    .query("sysparm_fields", "name%2Cvalue")
-                    .query("sysparm_offset", offset)
-                    .query("sysparm_query", "name=glide.sys.date_format^ORname=glide.sys.time_format")
-                    .invoke(HttpMethod.GET);
-
-                findResultNode(response).ifPresent(node -> processResult(node, n -> {
-                    if (n.hasNonNull("name") && n.hasNonNull("value")) {
-                        properties.put(
-                            n.findValue("name").asText(),
-                            n.findValue("value").asText()
-                        );
-                    }
-                }));
+        while (true) {
+            Response response = context.getClient().reset()
+                .types(MediaType.APPLICATION_JSON_TYPE)
+                .path("now")
+                .path(context.getConfiguration().getApiVersion())
+                .path("table")
+                .path("sys_properties")
+                .query("sysparm_exclude_reference_link", "true")
+                .query("sysparm_fields", "name%2Cvalue")
+                .query("sysparm_offset", offset)
+                .query("sysparm_query", "name=glide.sys.date_format^ORname=glide.sys.time_format")
+                .invoke(HttpMethod.GET);
 
-                Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
-                if (next.isPresent()) {
-                    offset = next.get();
-                } else {
-                    break;
+            findResultNode(response).ifPresent(node -> processResult(node, n -> {
+                if (n.hasNonNull("name") && n.hasNonNull("value")) {
+                    properties.putIfAbsent(
+                        n.findValue("name").asText(),
+                        n.findValue("value").asText()
+                    );
                 }
+            }));
+
+            Optional<String> next = ServiceNowHelper.findOffset(response, ServiceNowConstants.LINK_NEXT);
+            if (next.isPresent()) {
+                offset = next.get();
+            } else {
+                break;
             }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
         }
     }
 
@@ -378,7 +461,6 @@ final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
                 } catch (JsonProcessingException e) {
                     throw new RuntimeCamelException(e);
                 } finally {
-
                     context.getStack().pop();
                 }
             }
@@ -473,16 +555,16 @@ final class ServiceNowMetaDataExtension extends AbstractMetaDataExtension {
 
         MetaContext(Map<String, Object> parameters) {
             this.parameters = parameters;
-            this.configuration = getComponent(ServiceNowComponent.class).getConfiguration().copy();
+            this.configuration = new ServiceNowConfiguration();
             this.stack = new ArrayDeque<>();
 
             try {
                 IntrospectionSupport.setProperties(configuration, new HashMap<>(parameters));
             } catch (Exception e) {
-                throw new RuntimeException(e);
+                throw new IllegalStateException(e);
             }
 
-            this.instanceName = (String)parameters.getOrDefault("instanceName", getComponent(ServiceNowComponent.class).getInstanceName());
+            this.instanceName = (String)parameters.get("instanceName");
             this.objectType = (String)parameters.getOrDefault("objectType", ServiceNowConstants.RESOURCE_TABLE);
             this.objectName = (String)parameters.getOrDefault("objectName", configuration.getTable());
 
diff --git a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
index a384ed9..cb5d717 100644
--- a/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
+++ b/components/camel-servicenow/camel-servicenow-component/src/test/java/org/apache/camel/component/servicenow/ServiceNowMetaDataExtensionTest.java
@@ -55,6 +55,7 @@ public class ServiceNowMetaDataExtensionTest extends ServiceNowTestSupport {
         Map<String, Object> parameters = getParameters();
         parameters.put("objectType", "table");
         parameters.put("objectName", "incident");
+        parameters.put("metaType", "definition");
         //parameters.put("object.sys_user.fields", "first_name,last_name");
         //parameters.put("object.incident.fields", "caller_id,severity,resolved_at,sys_id");
         //parameters.put("object.incident.fields", "^sys_.*$");
@@ -83,6 +84,7 @@ public class ServiceNowMetaDataExtensionTest extends ServiceNowTestSupport {
     public void testImportMetaData() throws Exception {
         Map<String, Object> parameters = getParameters();
         parameters.put("objectType", "import");
+        parameters.put("metaType", "list");
         //parameters.put("object.sys_user.fields", "first_name,last_name");
         //parameters.put("object.incident.fields", "caller_id,severity,resolved_at,sys_id");
         //parameters.put("object.incident.fields", "^sys_.*$");