package com.thinkbiganalytics.nifi.rest.model.visitor; /*- * #%L * thinkbig-nifi-flow-visitor-model * %% * 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.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Represents the NiFi Process Group that can be visited and linked building a graph of connecting parents and children {@link NifiVisitableProcessor} * These are built from the {@link NifiFlowVisitor} */ public class NifiVisitableProcessGroup implements NifiVisitable { /** * all the processors visited in this group */ public Set<NifiVisitableProcessor> processors; /** * the Nifi process group */ private ProcessGroupDTO dto; /** * The parent process group for which this process group resides */ private ProcessGroupDTO parentProcessGroup; /** * the starting processors in this group which dont have any source connections in front of them */ private Set<NifiVisitableProcessor> startingProcessors; /** * the ending processors in this group that dont have any destination connections from them */ private Set<NifiVisitableProcessor> endingProcessors; /** * Map of the output port id to set of connecting processor ids */ private Map<String, Set<NifiVisitableProcessor>> outputPortProcessors; /** * Map of the input port id to set of connecting processor ids */ private Map<String, Set<NifiVisitableProcessor>> inputPortProcessors; private Set<ConnectionDTO> connections; /** * Create a new visitable group from a given NiFi process group * * @param dto a NiFi process group */ public NifiVisitableProcessGroup(ProcessGroupDTO dto) { this.dto = dto; startingProcessors = new HashSet<>(); endingProcessors = new HashSet<>(); outputPortProcessors = new HashMap<>(); inputPortProcessors = new HashMap<>(); processors = new HashSet<>(); connections = new HashSet<>(); if (dto.getContents() != null) { this.connections = dto.getContents().getConnections(); } } /** * Return a visitable processor, first looking at those that have been visited already by this process group, if not it will create a new one. * * @param nifiVisitor the visitor * @param processorDTO the processor to find * @return a visitable processor, wrapping the incoming processordto, to process or link to as a source/destination */ private NifiVisitableProcessor getOrCreateProcessor(NifiFlowVisitor nifiVisitor, ProcessorDTO processorDTO) { NifiVisitableProcessor processor = nifiVisitor.getProcessor(processorDTO.getId()); if (processor == null) { processor = new NifiVisitableProcessor(processorDTO); addProcessor(processor); } return processor; } /** * Return a visitable process group first looking at those that have been visited already by this parent process group, if not it will create a new one. * * @param nifiVisitor the visitor * @param processGroupDTO the group to find * @return the visitable process group wrapping the incoming processgroup */ private NifiVisitableProcessGroup getOrCreateProcessGroup(NifiFlowVisitor nifiVisitor, ProcessGroupDTO processGroupDTO) { NifiVisitableProcessGroup group = nifiVisitor.getProcessGroup(processGroupDTO.getId()); if (group == null) { group = new NifiVisitableProcessGroup(processGroupDTO); } return group; } /** * Return the parent process group for this group * * @return the parent process group for this group */ public ProcessGroupDTO getParentProcessGroup() { return parentProcessGroup; } /** * set the parent process group * * @param parentProcessGroup the group that is the parent group to this group */ public void setParentProcessGroup(ProcessGroupDTO parentProcessGroup) { this.parentProcessGroup = parentProcessGroup; } /** * Visit this process group using the supplied visitor * * @param nifiVisitor the visitor */ @Override public void accept(NifiFlowVisitor nifiVisitor) { if (dto.getContents() != null) { if (dto.getContents().getProcessors() != null) { for (ProcessorDTO processorDTO : dto.getContents().getProcessors()) { NifiVisitableProcessor processor = getOrCreateProcessor(nifiVisitor, processorDTO); nifiVisitor.visitProcessor(processor); } } if (dto.getContents().getProcessGroups() != null) { for (ProcessGroupDTO processGroupDTO : dto.getContents().getProcessGroups()) { if (processGroupDTO != null) { nifiVisitor.visitProcessGroup(getOrCreateProcessGroup(nifiVisitor, processGroupDTO)); } } } if (dto.getContents().getConnections() != null) { for (ConnectionDTO connectionDTO : dto.getContents().getConnections()) { nifiVisitor.visitConnection(new NifiVisitableConnection(this, connectionDTO)); } } populateStartingAndEndingProcessors(); } } /** * Return the NiFi ProcessGroup that this class wraps * * @return the NiFi process group item */ public ProcessGroupDTO getDto() { return dto; } /** * After visiting a processor, add it to the cache of processors referenced by this process group * * @param processor the processor that has been visited */ public void addProcessor(NifiVisitableProcessor processor) { processors.add(processor); } /** * Return a set of all the processors that dont have any incoming source connections * * @return a set of all the processors that dont have any incoming source connections */ public Set<NifiVisitableProcessor> getStartingProcessors() { return startingProcessors; } /** * Return a set of all the ending/leaf processors that dont have destination connections coming from them * * @return a set of all the ending/leaf processors that dont have destination connections coming from them */ public Set<NifiVisitableProcessor> getEndingProcessors() { return endingProcessors; } /** * Return the connection, if any, matching the incoming source connectionSourceId * * @param connectionSourceId the unique id for the connection source to find * @return a connection matching the incoming connectionSourceId, or Null if not found */ public ConnectionDTO getConnectionMatchingSourceId(final String connectionSourceId) { if (connections != null) { return Iterables.tryFind(connections, new Predicate<ConnectionDTO>() { @Override public boolean apply(ConnectionDTO connection) { return connection.getSource() != null && connection.getSource().getId().equals(connectionSourceId); } }).orNull(); } return null; } /** * Return the connection, if any, matching the incoming destination connectionDestinationId * * @param connectionDestinationId the unique id for the connection destination to find * @return a connection matching the incoming connectionDestinationId, or Null if not found */ public ConnectionDTO getConnectionMatchingDestinationId(final String connectionDestinationId) { if (connections != null) { return Iterables.tryFind(connections, new Predicate<ConnectionDTO>() { @Override public boolean apply(ConnectionDTO connection) { return connection.getDestination() != null && connection.getDestination().getId().equals(connectionDestinationId); } }).orNull(); } return null; } /** * populate the processors source/sink processors */ private void populateStartingAndEndingProcessors() { for (NifiVisitableProcessor processor : processors) { if (processor.isStart()) { startingProcessors.add(processor); } if (processor.isEnd()) { endingProcessors.add(processor); } } } /** * Return the processors that are attached to input ports * * @return processors attaached to a specific input port */ public Set<NifiVisitableProcessor> getInputPortProcessors(String inputPortId) { return inputPortProcessors.get(inputPortId); } /** * add the input port and processor to the map * * @param id the id of the input port * @param inputPortProcessor the processor connected to the input port */ public void addInputPortProcessor(String id, NifiVisitableProcessor inputPortProcessor) { if (!this.inputPortProcessors.containsKey(id)) { this.inputPortProcessors.put(id, new HashSet<>()); } this.inputPortProcessors.get(id).add(inputPortProcessor); } /** * Return the set of output port processors * * @param outputPortId the output port id * @return the processors connected to the supplied output port */ public Set<NifiVisitableProcessor> getOutputPortProcessors(String outputPortId) { return outputPortProcessors.get(outputPortId); } /** * Return the processor connected to the supplied output port * * @return the processor */ public NifiVisitableProcessor getOutputPortProcessor(String connectionSourceId) { if (outputPortProcessors.containsKey(connectionSourceId)) { return Lists.newArrayList(outputPortProcessors.get(connectionSourceId)).get(0); } return null; } /** * Add a processor connected to the supplied output port id * * @param id the output port id * @param outputPortProcessor the processor attached to this output port */ public void addOutputPortProcessor(String id, NifiVisitableProcessor outputPortProcessor) { if (!this.outputPortProcessors.containsKey(id)) { this.outputPortProcessors.put(id, new HashSet<>()); } this.outputPortProcessors.get(id).add(outputPortProcessor); } /** * Return the map of input port id to processors * * @return the map of input port id to processors */ public Map<String, Set<NifiVisitableProcessor>> getInputPortProcessors() { return inputPortProcessors; } /** * Return the map of output port id to processors * * @return the map of output port id to processors */ public Map<String, Set<NifiVisitableProcessor>> getOutputPortProcessors() { return outputPortProcessors; } /** * Return all the visited processors * * @return all the visited processors */ public Set<NifiVisitableProcessor> getProcessors() { return processors; } /** * Return all the all connections under this process group * * @return all the all connections under this process group */ public Set<ConnectionDTO> getConnections() { return connections; } }