| /* |
| * 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.maven; |
| |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.TimeUnit; |
| import java.util.regex.Pattern; |
| import java.util.stream.Collectors; |
| |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import org.apache.camel.component.salesforce.api.SalesforceException; |
| import org.apache.camel.component.salesforce.api.dto.GlobalObjects; |
| import org.apache.camel.component.salesforce.api.dto.SObject; |
| import org.apache.camel.component.salesforce.api.dto.SObjectDescription; |
| import org.apache.camel.component.salesforce.api.dto.SObjectField; |
| import org.apache.camel.component.salesforce.api.utils.JsonUtils; |
| import org.apache.camel.component.salesforce.internal.client.RestClient; |
| import org.apache.camel.component.salesforce.internal.client.SyncResponseCallback; |
| import org.apache.camel.util.ObjectHelper; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.logging.Log; |
| |
| final class ObjectDescriptions { |
| |
| private final RestClient client; |
| |
| private final Map<String, SObjectDescription> descriptions = new ConcurrentHashMap<>(); |
| |
| private final long responseTimeout; |
| |
| ObjectDescriptions(final RestClient client, final long responseTimeout, final String[] includes, final String includePattern, final String[] excludes, |
| final String excludePattern, final Log log) |
| throws MojoExecutionException { |
| this.client = client; |
| this.responseTimeout = responseTimeout; |
| |
| fetchSpecifiedDescriptions(includes, includePattern, excludes, excludePattern, log); |
| } |
| |
| int count() { |
| return descriptions.size(); |
| } |
| |
| SObjectDescription descriptionOf(final String name) { |
| return descriptions.computeIfAbsent(name, this::fetchDescriptionOf); |
| } |
| |
| boolean hasDescription(final String name) { |
| return descriptions.containsKey(name); |
| } |
| |
| List<SObjectField> externalIdsOf(final String name) { |
| return descriptionOf(name).getFields().stream().filter(SObjectField::isExternalId).collect(Collectors.toList()); |
| } |
| |
| boolean hasExternalIds(final String name) { |
| return descriptionOf(name).getFields().stream().anyMatch(SObjectField::isExternalId); |
| } |
| |
| Iterable<SObjectDescription> fetched() { |
| return descriptions.values(); |
| } |
| |
| private SObjectDescription fetchDescriptionOf(final String name) { |
| try { |
| final ObjectMapper mapper = JsonUtils.createObjectMapper(); |
| final SyncResponseCallback callback = new SyncResponseCallback(); |
| |
| client.getDescription(name, Collections.emptyMap(), callback); |
| if (!callback.await(responseTimeout, TimeUnit.MILLISECONDS)) { |
| throw new MojoExecutionException("Timeout waiting for getDescription for sObject " + name); |
| } |
| final SalesforceException ex = callback.getException(); |
| if (ex != null) { |
| throw ex; |
| } |
| final SObjectDescription description = mapper.readValue(callback.getResponse(), SObjectDescription.class); |
| |
| // remove some of the unused used metadata |
| // properties in order to minimize the code size |
| // for CAMEL-11310 |
| return description.prune(); |
| } catch (final Exception e) { |
| throw new IllegalStateException("Error getting SObject description for '" + name + "': " + e.getMessage(), e); |
| } |
| } |
| |
| private void fetchSpecifiedDescriptions(final String[] includes, final String includePattern, final String[] excludes, final String excludePattern, final Log log) |
| throws MojoExecutionException { |
| // use Jackson json |
| final ObjectMapper mapper = JsonUtils.createObjectMapper(); |
| |
| // call getGlobalObjects to get all SObjects |
| final Set<String> objectNames = new TreeSet<>(); |
| final SyncResponseCallback callback = new SyncResponseCallback(); |
| try { |
| log.info("Getting Salesforce Objects..."); |
| client.getGlobalObjects(Collections.emptyMap(), callback); |
| if (!callback.await(responseTimeout, TimeUnit.MILLISECONDS)) { |
| throw new MojoExecutionException("Timeout waiting for getGlobalObjects!"); |
| } |
| final SalesforceException ex = callback.getException(); |
| if (ex != null) { |
| throw ex; |
| } |
| final GlobalObjects globalObjects = mapper.readValue(callback.getResponse(), GlobalObjects.class); |
| |
| // create a list of object names |
| for (final SObject sObject : globalObjects.getSobjects()) { |
| objectNames.add(sObject.getName()); |
| } |
| } catch (final Exception e) { |
| throw new MojoExecutionException("Error getting global Objects: " + e.getMessage(), e); |
| } |
| |
| // check if we are generating POJOs for all objects or not |
| if (includes != null && includes.length > 0 || excludes != null && excludes.length > 0 || ObjectHelper.isNotEmpty(includePattern) |
| || ObjectHelper.isNotEmpty(excludePattern)) { |
| |
| filterObjectNames(objectNames, includes, includePattern, excludes, excludePattern, log); |
| |
| } else { |
| log.warn(String.format("Generating Java classes for all %s Objects, this may take a while...", objectNames.size())); |
| } |
| |
| log.info("Retrieving Object descriptions..."); |
| for (final String name : objectNames) { |
| descriptionOf(name); |
| } |
| } |
| |
| private static void filterObjectNames(final Set<String> objectNames, final String[] includes, final String includePattern, final String[] excludes, final String excludePattern, |
| final Log log) |
| throws MojoExecutionException { |
| log.info("Looking for matching Object names..."); |
| // create a list of accepted names |
| final Set<String> includedNames = new HashSet<>(); |
| if (includes != null && includes.length > 0) { |
| for (String name : includes) { |
| name = name.trim(); |
| if (name.isEmpty()) { |
| throw new MojoExecutionException("Invalid empty name in includes"); |
| } |
| includedNames.add(name); |
| } |
| } |
| |
| final Set<String> excludedNames = new HashSet<>(); |
| if (excludes != null && excludes.length > 0) { |
| for (String name : excludes) { |
| name = name.trim(); |
| if (name.isEmpty()) { |
| throw new MojoExecutionException("Invalid empty name in excludes"); |
| } |
| excludedNames.add(name); |
| } |
| } |
| |
| // check whether a pattern is in effect |
| Pattern incPattern; |
| if (includePattern != null && !includePattern.trim().isEmpty()) { |
| incPattern = Pattern.compile(includePattern.trim()); |
| } else if (includedNames.isEmpty()) { |
| // include everything by default if no include names are set |
| incPattern = Defaults.MATCH_EVERYTHING_PATTERN; |
| } else { |
| // include nothing by default if include names are set |
| incPattern = Defaults.MATCH_NOTHING_PATTERN; |
| } |
| |
| // check whether a pattern is in effect |
| Pattern excPattern; |
| if (excludePattern != null && !excludePattern.trim().isEmpty()) { |
| excPattern = Pattern.compile(excludePattern.trim()); |
| } else { |
| // exclude nothing by default |
| excPattern = Defaults.MATCH_NOTHING_PATTERN; |
| } |
| |
| final Set<String> acceptedNames = new HashSet<>(); |
| for (final String name : objectNames) { |
| // name is included, or matches include pattern |
| // and is not excluded and does not match exclude pattern |
| if ((includedNames.contains(name) || incPattern.matcher(name).matches()) && !excludedNames.contains(name) && !excPattern.matcher(name).matches()) { |
| acceptedNames.add(name); |
| } |
| } |
| objectNames.clear(); |
| objectNames.addAll(acceptedNames); |
| |
| log.info(String.format("Found %s matching Objects", objectNames.size())); |
| } |
| } |