package com.thinkbiganalytics.feedmgr.service.template; /*- * #%L * thinkbig-feed-manager-controller * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed 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. * #L% */ import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.thinkbiganalytics.feedmgr.rest.model.FeedMetadata; import com.thinkbiganalytics.feedmgr.rest.model.RegisteredTemplate; import com.thinkbiganalytics.feedmgr.rest.model.RegisteredTemplateRequest; import com.thinkbiganalytics.feedmgr.rest.model.ReusableTemplateConnectionInfo; import com.thinkbiganalytics.feedmgr.security.FeedServicesAccessControl; import com.thinkbiganalytics.feedmgr.service.template.TemplateModelTransform.TEMPLATE_TRANSFORMATION_TYPE; import com.thinkbiganalytics.metadata.api.MetadataAccess; import com.thinkbiganalytics.metadata.api.template.FeedManagerTemplate; import com.thinkbiganalytics.metadata.api.template.FeedManagerTemplateProvider; import com.thinkbiganalytics.nifi.rest.client.LegacyNifiRestClient; import com.thinkbiganalytics.nifi.rest.client.NifiClientRuntimeException; import com.thinkbiganalytics.nifi.rest.client.NifiComponentNotFoundException; import com.thinkbiganalytics.nifi.rest.model.NifiProperty; import com.thinkbiganalytics.nifi.rest.support.NifiConstants; import com.thinkbiganalytics.nifi.rest.support.NifiFeedConstants; import com.thinkbiganalytics.nifi.rest.support.NifiPropertyUtil; import com.thinkbiganalytics.nifi.rest.support.NifiTemplateUtil; import com.thinkbiganalytics.security.AccessController; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; import org.apache.nifi.web.api.dto.TemplateDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.Principal; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.inject.Inject; /** * */ public class RegisteredTemplateService { private static final Logger log = LoggerFactory.getLogger(RegisteredTemplateService.class); @Inject FeedManagerTemplateProvider templateProvider; @Inject MetadataAccess metadataAccess; @Inject TemplateModelTransform templateModelTransform; @Inject private AccessController accessController; @Inject private LegacyNifiRestClient nifiRestClient; @Inject private RegisteredTemplateUtil registeredTemplateUtil; /** * Gets a Registered Template or returns null if not found by various means passed in via the request object * * @param registeredTemplateRequest a request to get a registered template * @return the RegisteredTemplate or null if not found */ public RegisteredTemplate findRegisteredTemplate(RegisteredTemplateRequest registeredTemplateRequest) { String templateId = registeredTemplateRequest.getTemplateId(); String templateName = registeredTemplateRequest.getTemplateName(); //if we are looking for a given template as a request from a Feed, we need to query and access it via a service account. //otherwise we will access it as the user Principal[] principals = null; if (registeredTemplateRequest.isFeedEdit()) { principals = new Principal[1]; principals[0] = MetadataAccess.SERVICE; } else { principals = new Principal[0]; } //The default transformation type will not include sensitive property values. //if requested as a template or feed edit, it will include the encrypted sensitive property values TEMPLATE_TRANSFORMATION_TYPE transformationType = TEMPLATE_TRANSFORMATION_TYPE.WITH_FEED_NAMES; if (registeredTemplateRequest.isTemplateEdit() || registeredTemplateRequest.isFeedEdit() || registeredTemplateRequest.isIncludeSensitiveProperties()) { transformationType = TEMPLATE_TRANSFORMATION_TYPE.WITH_SENSITIVE_DATA; } RegisteredTemplate registeredTemplate = findRegisteredTemplateById(templateId, transformationType, principals); //if it is null check to see if the template exists in nifi and is already registered if (registeredTemplate == null) { // log.info("Attempt to get Template with id {}, returned null. This id must be one registed in Nifi... attempt to query Nifi for this template ", templateId); registeredTemplate = findRegisteredTemplateByNiFiIdentifier(templateId, transformationType, principals); } if (registeredTemplate == null) { //attempt to look by name registeredTemplate = findRegisteredTemplateByName(templateName, transformationType, principals); } if (registeredTemplate != null) { if (registeredTemplateRequest.isIncludeAllProperties()) { registeredTemplate = mergeRegisteredTemplateProperties(registeredTemplate, registeredTemplateRequest); } if (NifiPropertyUtil.containsPropertiesForProcessorMatchingType(registeredTemplate.getProperties(), NifiFeedConstants.TRIGGER_FEED_PROCESSOR_CLASS)) { registeredTemplate.setAllowPreconditions(true); } else { registeredTemplate.setAllowPreconditions(false); } } return registeredTemplate; } /** * Find a template by the Kylo Id * * @param templateId The Kylo {@link RegisteredTemplate#id} * @return the RegisteredTemplate matching the id or null if not found */ public RegisteredTemplate findRegisteredTemplateById(final String templateId) { return findRegisteredTemplateById(templateId, null); } /** * Find a template by the Kylo Id * * @param templateId The Kylo {@link RegisteredTemplate#id} * @param principals list or principals required to access * @return the RegisteredTemplate matching the id or null if not found */ private RegisteredTemplate findRegisteredTemplateById(final String templateId, TEMPLATE_TRANSFORMATION_TYPE transformationType, Principal... principals) { if (StringUtils.isBlank(templateId)) { return null; } else { return metadataAccess.read(() -> { this.accessController.checkPermission(AccessController.SERVICES, FeedServicesAccessControl.ACCESS_TEMPLATES); RegisteredTemplate registeredTemplate = null; FeedManagerTemplate.ID domainId = templateProvider.resolveId(templateId); FeedManagerTemplate domainTemplate = templateProvider.findById(domainId); if (domainTemplate != null) { //transform it registeredTemplate = templateModelTransform.getTransformationFunction(transformationType).apply(domainTemplate); } if (registeredTemplate != null) { registeredTemplate.initializeProcessors(); ensureNifiTemplate(registeredTemplate); } return registeredTemplate; }, principals); } } /** * Find a template by the nifi id * * @param nifiTemplateId the nifi id * @return the RegisteredTemplate matching the passed in nifiTemplateId, or null if not found */ public RegisteredTemplate findRegisteredTemplateByNiFiIdentifier(final String nifiTemplateId) { return findRegisteredTemplateByNiFiIdentifier(nifiTemplateId, null); } /** * Find a template by the nifi id * * @param nifiTemplateId the nifi id * @param principals list of principals required to access * @return the RegisteredTemplate matching the passed in nifiTemplateId, or null if not found */ private RegisteredTemplate findRegisteredTemplateByNiFiIdentifier(final String nifiTemplateId, TEMPLATE_TRANSFORMATION_TYPE transformationType, Principal... principals) { if (StringUtils.isBlank(nifiTemplateId)) { return null; } return metadataAccess.read(() -> { this.accessController.checkPermission(AccessController.SERVICES, FeedServicesAccessControl.ACCESS_TEMPLATES); RegisteredTemplate registeredTemplate = null; FeedManagerTemplate template = templateProvider.findByNifiTemplateId(nifiTemplateId); if (template != null) { registeredTemplate = templateModelTransform.getTransformationFunction(transformationType).apply(template); } return registeredTemplate; }, principals); } /** * Find a template by the name * * @param templateName the name of the template * @return the RegisteredTemplate matching the passed in name or null if not found */ public RegisteredTemplate findRegisteredTemplateByName(final String templateName) { return findRegisteredTemplateByName(templateName, null); } /** * Find a template by the name * * @param templateName the name of the template * @param principals list of principals required to access * @return the RegisteredTemplate matching the passed in name or null if not found */ public RegisteredTemplate findRegisteredTemplateByName(final String templateName, TEMPLATE_TRANSFORMATION_TYPE transformationType, Principal... principals) { return metadataAccess.read(() -> { this.accessController.checkPermission(AccessController.SERVICES, FeedServicesAccessControl.ACCESS_TEMPLATES); RegisteredTemplate registeredTemplate = null; FeedManagerTemplate template = templateProvider.findByName(templateName); if (template != null) { registeredTemplate = templateModelTransform.getTransformationFunction(transformationType).apply(template); } return registeredTemplate; }, principals); } /** * Return a registered template object that is populated for use with updating in Kylo * * @param registeredTemplateRequest the request to get a registered template * @return a RegisteredTemplate object mapping either one already defined in Kylo, or a new template that maps to one in NiFi */ public RegisteredTemplate getRegisteredTemplateForUpdate(RegisteredTemplateRequest registeredTemplateRequest) { RegisteredTemplate registeredTemplate = findRegisteredTemplate(registeredTemplateRequest); if (registeredTemplate == null) { registeredTemplate = nifiTemplateToRegisteredTemplate(registeredTemplateRequest.getNifiTemplateId()); } if (registeredTemplate == null) { //throw exception } else { Set<PortDTO> ports = null; // fetch ports for this template try { if (registeredTemplate.getNifiTemplate() != null) { ports = nifiRestClient.getPortsForTemplate(registeredTemplate.getNifiTemplate()); } else { ports = nifiRestClient.getPortsForTemplate(registeredTemplate.getNifiTemplateId()); } } catch (NifiComponentNotFoundException notFoundException) { syncNiFiTemplateId(registeredTemplate); ports = nifiRestClient.getPortsForTemplate(registeredTemplate.getNifiTemplateId()); } if (ports == null) { ports = new HashSet<>(); } List<PortDTO> outputPorts = ports.stream().filter(portDTO -> portDTO != null && NifiConstants.NIFI_PORT_TYPE.OUTPUT_PORT.name().equalsIgnoreCase(portDTO.getType())).collect(Collectors.toList()); List<PortDTO> inputPorts = ports.stream().filter(portDTO -> portDTO != null && NifiConstants.NIFI_PORT_TYPE.INPUT_PORT.name().equalsIgnoreCase(portDTO.getType())).collect(Collectors.toList()); registeredTemplate.setReusableTemplate(inputPorts != null && !inputPorts.isEmpty()); List<ReusableTemplateConnectionInfo> reusableTemplateConnectionInfos = registeredTemplate.getReusableTemplateConnections(); List<ReusableTemplateConnectionInfo> updatedConnectionInfo = new ArrayList<>(); for (final PortDTO port : outputPorts) { ReusableTemplateConnectionInfo reusableTemplateConnectionInfo = null; if (reusableTemplateConnectionInfos != null && !reusableTemplateConnectionInfos.isEmpty()) { reusableTemplateConnectionInfo = Iterables.tryFind(reusableTemplateConnectionInfos, reusableTemplateConnectionInfo1 -> reusableTemplateConnectionInfo1 .getFeedOutputPortName() .equalsIgnoreCase(port.getName())).orNull(); } if (reusableTemplateConnectionInfo == null) { reusableTemplateConnectionInfo = new ReusableTemplateConnectionInfo(); reusableTemplateConnectionInfo.setFeedOutputPortName(port.getName()); } updatedConnectionInfo.add(reusableTemplateConnectionInfo); } registeredTemplate.setReusableTemplateConnections(updatedConnectionInfo); registeredTemplate.initializeProcessors(); ensureRegisteredTemplateInputProcessors(registeredTemplate); } return registeredTemplate; } public List<RegisteredTemplate> getRegisteredTemplates() { return metadataAccess.read(() -> { this.accessController.checkPermission(AccessController.SERVICES, FeedServicesAccessControl.ACCESS_TEMPLATES); List<RegisteredTemplate> registeredTemplates = null; List<FeedManagerTemplate> templates = templateProvider.findAll(); if (templates != null) { templates.stream().filter(t -> t.getNifiTemplateId() == null).forEach(t -> { ensureNifiTemplateId(t); }); registeredTemplates = templateModelTransform.domainToRegisteredTemplateWithFeedNames(templates); } return registeredTemplates; }); } /** * this will return a RegisteredTemplate object for a given NiFi template Id. * This is to be used for new templates that are going to be registered with Kylo. * Callers of this method should ensure that a template of this id is not already registered * * @param nifiTemplateId the nifi template identifier * @return a RegisteredTemplate object of null if not found in NiFi */ private RegisteredTemplate nifiTemplateToRegisteredTemplate(String nifiTemplateId) { RegisteredTemplate registeredTemplate = null; List<NifiProperty> properties = new ArrayList<>(); TemplateDTO nifiTemplate = nifiRestClient.getTemplateById(nifiTemplateId); if (nifiTemplate != null) { registeredTemplate = new RegisteredTemplate(); registeredTemplate.setNifiTemplateId(nifiTemplateId); properties = nifiRestClient.getPropertiesForTemplate(nifiTemplate, true); registeredTemplate.setNifiTemplate(nifiTemplate); registeredTemplate.setTemplateName(nifiTemplate.getName()); registeredTemplate.setProperties(properties); } return registeredTemplate; } /** * Merge all saved properties on the RegisteredTemplate along with the properties in the NiFi template * The resulting object will have the {@link RegisteredTemplate#properties} updated so they are in sync with NiFi. * * @return a RegisteredTemplate that has the properties updated with those in NiFi */ public RegisteredTemplate mergeRegisteredTemplateProperties(RegisteredTemplate registeredTemplate, RegisteredTemplateRequest registeredTemplateRequest) { if (registeredTemplate != null) { log.info("Merging properties for template {} ({})", registeredTemplate.getTemplateName(), registeredTemplate.getId()); List<NifiProperty> properties = null; int matchCount = 0; //get the nifi template associated with this one that is registered TemplateDTO templateDTO = registeredTemplate.getNifiTemplate(); if (templateDTO == null) { templateDTO = ensureNifiTemplate(registeredTemplate); } if (templateDTO != null) { registeredTemplate.setNifiTemplate(templateDTO); properties = nifiRestClient.getPropertiesForTemplate(templateDTO, registeredTemplateRequest.isIncludePropertyDescriptors()); //first attempt to match the properties by the processorid and processor name NifiPropertyUtil .matchAndSetPropertyByIdKey(properties, registeredTemplate.getProperties(), NifiPropertyUtil.PROPERTY_MATCH_AND_UPDATE_MODE.UPDATE_ALL_PROPERTIES); } if (properties != null) { //match the properties to the processors by the processor name //expression ${metdata.} properties will not be reset NifiPropertyUtil.matchAndSetPropertyByProcessorName(properties, registeredTemplate.getProperties(), NifiPropertyUtil.PROPERTY_MATCH_AND_UPDATE_MODE.UPDATE_ALL_PROPERTIES); } if (templateDTO != null && !templateDTO.getId().equalsIgnoreCase(registeredTemplate.getNifiTemplateId())) { syncNiFiTemplateId(registeredTemplate); } if (properties == null) { properties = new ArrayList<>(); } //merge with the registered properties RegisteredTemplate copy = new RegisteredTemplate(registeredTemplate); copy.setProperties(properties); copy.setNifiTemplate(registeredTemplate.getNifiTemplate()); registeredTemplate = copy; } else { log.info("Unable to merge Registered Template. It is null"); } return registeredTemplate; } public FeedMetadata mergeTemplatePropertiesWithFeed(FeedMetadata feedMetadata) { //gets the feed data and then gets the latest template associated with that feed and merges the properties into the feed RegisteredTemplate registeredTemplate = findRegisteredTemplate( new RegisteredTemplateRequest.Builder().templateId(feedMetadata.getTemplateId()).isFeedEdit(true).nifiTemplateId(feedMetadata.getTemplateId()).includeAllProperties(true).build()); if (registeredTemplate != null) { feedMetadata.setTemplateId(registeredTemplate.getId()); NifiPropertyUtil .matchAndSetPropertyByProcessorName(registeredTemplate.getProperties(), feedMetadata.getProperties(), NifiPropertyUtil.PROPERTY_MATCH_AND_UPDATE_MODE.FEED_DETAILS_MATCH_TEMPLATE); //detect template properties that dont match the feed.properties from the registeredtemplate ensureFeedPropertiesExistInTemplate(feedMetadata, registeredTemplate); feedMetadata.setProperties(registeredTemplate.getProperties()); registeredTemplate.initializeProcessors(); feedMetadata.setRegisteredTemplate(registeredTemplate); } return feedMetadata; } /** * If a Template changes the Processor Names the Feed Properties will no longer be associated to the correct processors * This will match any feed properties to a whose processor name has changed in * the template to the template processor/property based upon the template processor type. */ private void ensureFeedPropertiesExistInTemplate(FeedMetadata feed, RegisteredTemplate registeredTemplate) { Set<String> templateProcessors = registeredTemplate.getProperties().stream().map(property -> property.getProcessorName()).collect(Collectors.toSet()); //Store the template Properties Map<String, String> templateProcessorIdProcessorNameMap = new HashMap<>(); Map<String, String> templateProcessorTypeProcessorIdMap = new HashMap<>(); registeredTemplate.getProperties().stream().filter(property -> !templateProcessorIdProcessorNameMap.containsKey(property.getProcessorId())).forEach(property1 -> { templateProcessorIdProcessorNameMap.put(property1.getProcessorId(), property1.getProcessorName()); templateProcessorTypeProcessorIdMap.put(property1.getProcessorType(), property1.getProcessorId()); }); Map<String, Map<String, NifiProperty>> templatePropertiesByProcessorIdMap = new HashMap<>(); registeredTemplate.getProperties().stream().forEach(property -> { templatePropertiesByProcessorIdMap.computeIfAbsent(property.getProcessorId(), key -> new HashMap<String, NifiProperty>()).put(property.getKey(), property); }); //store the Feed Properties Map<String, String> processorIdProcessorTypeMap = new HashMap<>(); feed.getProperties().stream().filter(property -> !processorIdProcessorTypeMap.containsKey(property.getProcessorId())).forEach(property1 -> { processorIdProcessorTypeMap.put(property1.getProcessorId(), property1.getProcessorType()); }); feed.getProperties().stream().filter(property -> !templateProcessors.contains(property.getProcessorName())).forEach(property -> { //if the property doesn't match the template but the type matches try to merge in the feed properties overwriting the template ones String processorType = processorIdProcessorTypeMap.get(property.getProcessorId()); if (processorType != null) { String templateProcessorId = templateProcessorTypeProcessorIdMap.get(processorType); if (templateProcessorId != null && templateProcessorIdProcessorNameMap.containsKey(templateProcessorId)) { NifiProperty templateProperty = templatePropertiesByProcessorIdMap.get(templateProcessorId).get(property.getKey()); if (templateProperty != null) { templateProperty.setValue(property.getValue()); templateProperty.setRenderType(property.getRenderType()); templateProperty.setRenderOptions(property.getRenderOptions()); } } } }); } /** * Return the NiFi {@link TemplateDTO} object fully populated and sets this to the incoming {@link RegisteredTemplate#nifiTemplate} * If at first looking at the {@link RegisteredTemplate#nifiTemplateId} it is unable to find the template it will then fallback and attempt to find the template by its name * * @param registeredTemplate a registered template object * @return the NiFi template */ private TemplateDTO ensureNifiTemplate(RegisteredTemplate registeredTemplate) { if (registeredTemplate.getNifiTemplate() == null) { TemplateDTO templateDTO = null; try { try { templateDTO = nifiRestClient.getTemplateById(registeredTemplate.getNifiTemplateId()); } catch (NifiComponentNotFoundException e) { //this is fine... we can safely proceeed if not found. } if (templateDTO == null) { templateDTO = nifiRestClient.getTemplateByName(registeredTemplate.getTemplateName()); if (templateDTO != null) { //getting the template by the name will not get all the properties. //refetch it by the name to get the FlowSnippet //populate the snippet templateDTO = nifiRestClient.getTemplateById(templateDTO.getId()); } } if (templateDTO != null) { registeredTemplate.setNifiTemplate(templateDTO); registeredTemplate.setNifiTemplateId(registeredTemplate.getNifiTemplate().getId()); } } catch (NifiClientRuntimeException e) { log.error("Error attempting to get the NifiTemplate TemplateDTO object for {} using nifiTemplateId of {} ", registeredTemplate.getTemplateName(), registeredTemplate.getNifiTemplateId()); } } return registeredTemplate.getNifiTemplate(); } /** * Ensures that the {@code RegisteredTemplate#inputProcessors} list is populated not only with the processors which were defined as having user inputs, but also those that done require any input */ public void ensureRegisteredTemplateInputProcessors(RegisteredTemplate registeredTemplate) { registeredTemplate.initializeInputProcessors(); List<RegisteredTemplate.Processor> nifiProcessors = getInputProcessorsInNifTemplate(registeredTemplate); if (nifiProcessors == null) { nifiProcessors = Collections.emptyList(); } List<RegisteredTemplate.Processor> validInputProcessors = nifiProcessors.stream().filter(RegisteredTemplate.isValidInputProcessor()).collect(Collectors.toList()); //add in any processors not in the map validInputProcessors.stream().forEach(processor -> { boolean match = registeredTemplate.getInputProcessors().stream().anyMatch( registeredProcessor -> registeredProcessor.getId().equals(processor.getId()) || (registeredProcessor.getType().equals(processor.getType()) && registeredProcessor.getName() .equals(processor.getName()))); if (!match) { log.info("Adding Processor {} to registered ", processor.getName()); registeredTemplate.getInputProcessors().add(processor); } }); } /** * Ensure that the NiFi template Ids are correct and match our metadata for the Template Name * * @param template a registered template * @return the updated template with the {@link RegisteredTemplate#nifiTemplateId} correctly matching NiFi */ public RegisteredTemplate syncNiFiTemplateId(RegisteredTemplate template) { String oldId = template.getNifiTemplateId(); if (oldId == null) { oldId = ""; } String nifiTemplateId = nifiTemplateIdForTemplateName(template.getTemplateName()); if (nifiTemplateId != null && !oldId.equalsIgnoreCase(nifiTemplateId)) { template.setNifiTemplateId(nifiTemplateId); RegisteredTemplate t = findRegisteredTemplateById(template.getId()); t.setNifiTemplateId(nifiTemplateId); return metadataAccess.commit(() -> { return saveTemplate(t); }, MetadataAccess.ADMIN); } return template; } private FeedManagerTemplate ensureNifiTemplateId(FeedManagerTemplate feedManagerTemplate) { if (feedManagerTemplate.getNifiTemplateId() == null) { String nifiTemplateId = nifiTemplateIdForTemplateName(feedManagerTemplate.getName()); feedManagerTemplate.setNifiTemplateId(nifiTemplateId); } return feedManagerTemplate; } public RegisteredTemplate saveRegisteredTemplate(final RegisteredTemplate registeredTemplate) { return saveRegisteredTemplate(registeredTemplate, true); } private RegisteredTemplate saveRegisteredTemplate(final RegisteredTemplate registeredTemplate, boolean reorder) { List<String> templateOrder = registeredTemplate.getTemplateOrder(); registeredTemplate.setUpdated(false); RegisteredTemplate savedTemplate = metadataAccess.commit(() -> { this.accessController.checkPermission(AccessController.SERVICES, FeedServicesAccessControl.EDIT_TEMPLATES); return saveTemplate(registeredTemplate); }); //order it if (reorder) { if (StringUtils.isBlank(registeredTemplate.getId())) { templateOrder = templateOrder.stream().map(template -> { if ("NEW".equals(template)) { return savedTemplate.getId(); } else { return template; } }).collect(Collectors.toList()); } orderTemplates(templateOrder, Sets.newHashSet(savedTemplate.getId())); } return savedTemplate; } /** * This needs to be wrapped in a MetadataAccess transaction * * @param registeredTemplate the template to save * @return the saved template */ private RegisteredTemplate saveTemplate(RegisteredTemplate registeredTemplate) { //ensure that the incoming template name doesnt already exist. //if so remove and replace with this one RegisteredTemplate template = findRegisteredTemplate(RegisteredTemplateRequest.requestByTemplateName(registeredTemplate.getTemplateName())); if (registeredTemplate.getId() == null && template != null) { registeredTemplate.setId(template.getId()); } if (template != null && !template.getId().equalsIgnoreCase(registeredTemplate.getId())) { //Warning cant save.. duplicate Name log.error("Unable to save template {}. There is already a template with this name registered in the system", registeredTemplate.getTemplateName()); return null; } else { log.info("About to save Registered Template {} ({}), nifi template Id of {} ", registeredTemplate.getTemplateName(), registeredTemplate.getId(), registeredTemplate.getNifiTemplateId()); ensureRegisteredTemplateInputProcessors(registeredTemplate); FeedManagerTemplate domain = templateModelTransform.REGISTERED_TEMPLATE_TO_DOMAIN.apply(registeredTemplate); ensureNifiTemplateId(domain); if (domain != null) { log.info("Domain Object is {} ({}), nifi template Id of {}", domain.getName(), domain.getId(), domain.getNifiTemplateId()); } domain = templateProvider.update(domain); //query it back to display to the ui domain = templateProvider.findById(domain.getId()); RegisteredTemplate updatedTemplate = templateModelTransform.DOMAIN_TO_REGISTERED_TEMPLATE.apply(domain); updatedTemplate.setUpdated(true); return updatedTemplate; } } /** * Return the processors in RegisteredTemplate that are input processors ( processors without any incoming connections). * This will call out to NiFi to inspect and obtain the NiFi template if it doesn't exist on the registeredTemplate * * @param registeredTemplate the template to inspect * @return the processors in RegisteredTemplate that are input processors without any incoming connections */ public List<RegisteredTemplate.Processor> getInputProcessorsInNifTemplate(RegisteredTemplate registeredTemplate) { TemplateDTO nifiTemplate = registeredTemplate.getNifiTemplate(); if (nifiTemplate == null) { nifiTemplate = ensureNifiTemplate(registeredTemplate); } return getInputProcessorsInNifTemplate(nifiTemplate); } /** * Return the input processors (processors without any incoming connections) in a NiFi template object * * @param nifiTemplate the NiFi template * @return the input processors (processors without any incoming connections) in a NiFi template object */ public List<RegisteredTemplate.Processor> getInputProcessorsInNifTemplate(TemplateDTO nifiTemplate) { List<RegisteredTemplate.Processor> processors = new ArrayList<>(); if (nifiTemplate != null) { List<ProcessorDTO> inputProcessors = NifiTemplateUtil.getInputProcessorsForTemplate(nifiTemplate); if (inputProcessors != null) { inputProcessors.stream().forEach(processorDTO -> { RegisteredTemplate.Processor p = registeredTemplateUtil.toRegisteredTemplateProcessor(processorDTO, false); p.setInputProcessor(true); processors.add(p); }); } } return processors; } /** * pass in the Template Ids in Order */ public void orderTemplates(List<String> orderedTemplateIds, Set<String> exclude) { metadataAccess.commit(() -> { this.accessController.checkPermission(AccessController.SERVICES, FeedServicesAccessControl.EDIT_TEMPLATES); if (orderedTemplateIds != null && !orderedTemplateIds.isEmpty()) { IntStream.range(0, orderedTemplateIds.size()).forEach(i -> { String id = orderedTemplateIds.get(i); if (!"NEW".equals(id) && (exclude == null || (exclude != null && !exclude.contains(id)))) { FeedManagerTemplate template = templateProvider.findById(templateProvider.resolveId(id)); if (template != null) { if (template.getOrder() == null || !template.getOrder().equals(new Long(i))) { //save the new order template.setOrder(new Long(i)); templateProvider.update(template); } } } }); } }, MetadataAccess.ADMIN); } /** * Return the NiFi template id for the incoming template name * * @param templateName the name of the template * @return the NiFi template id for the incoming template name, null if not found */ public String nifiTemplateIdForTemplateName(String templateName) { TemplateDTO templateDTO = null; templateDTO = nifiRestClient.getTemplateByName(templateName); if (templateDTO != null) { return templateDTO.getId(); } return null; } }