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.thinkbiganalytics.nifi.rest.model.flow.NiFiFlowProcessorConnection; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.Set; /** * Visit a NiFi processor and connect it to other processors * * @see NifiFlowVisitor */ public class NifiVisitableProcessor implements NifiVisitable { private static final Logger log = LoggerFactory.getLogger(NifiVisitableProcessor.class); private Set<NifiVisitableProcessor> sources; //parents private Set<NifiVisitableProcessor> destinations; //children /** * The NiFi processor id **/ private String id; private Set<NiFiFlowProcessorConnection> sourceConnectionIdentifiers; private Set<NiFiFlowProcessorConnection> destinationConnectionIdentifiers; private ProcessorDTO dto; public NifiVisitableProcessor(ProcessorDTO dto) { this.dto = dto; this.id = dto.getId(); } /** * visit the processor with the supplied visitor * * @param nifiVisitor the visitor */ @Override public void accept(NifiFlowVisitor nifiVisitor) { nifiVisitor.visitProcessor(this); } /** * connect this processor to a incoming source processor * * @param dto the sorce processor */ public void addSource(NifiVisitableProcessor dto) { getSources().add(dto); } /** * connect this processor to a outgoing destination * * @param dto the destination processor */ public void addDestination(NifiVisitableProcessor dto) { getDestinations().add(dto); } /** * Return all processors that come directly before this processor * * @return the source processors connecting to this processor */ public Set<NifiVisitableProcessor> getSources() { if (sources == null) { sources = new HashSet<>(); } return sources; } /** * Return all the processors that connect after this processor * * @return the destination processors */ public Set<NifiVisitableProcessor> getDestinations() { if (destinations == null) { destinations = new HashSet<>(); } return destinations; } /** * Return the NiFi object representing this processor * * @return the nifi processor */ public ProcessorDTO getDto() { return dto; } /** * set the NiFi processor * * @param dto the NiFi processor */ public void setDto(ProcessorDTO dto) { this.dto = dto; } /** * Check to see if that this processor does not have any input/sources connected into it * * @return {@code true} if no processors are connected as sources to this processor, {@code false} if otherwise */ public boolean isStart() { return !getDestinations().isEmpty() && getSources().isEmpty(); } /** * Check to see this processor is a leaft node meaning that this processor does not have any output/destinations connected from it * * @return {@code true} if no processors are connected as outputs from this processor, {@code false} if otherwise */ public boolean isEnd() { return !getSources().isEmpty() && getDestinations().isEmpty(); } /** * Check to see if this processor Id matches another incoming processor */ @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } NifiVisitableProcessor processor = (NifiVisitableProcessor) o; return id.equals(processor.id); } @Override public int hashCode() { return id.hashCode(); } /*** * Print out the processor to log */ public void print() { print(0); } /** * Print out the processor to the log */ public void print(Integer level) { log.info(level + ". " + getDto().getName()); Set<String> printed = new HashSet<>(); printed.add(this.getId()); Integer nextLevel = level + 1; for (NifiVisitableProcessor child : getDestinations()) { if (!child.containsDestination(this) && !child.containsDestination(child) && !child.equals(this) && !printed.contains(child.getId())) { child.print(nextLevel); printed.add(child.getId()); } } } /** * Check to see if this processor contains an incoming processor * * @param parent the processor to check for in this processors {@link this#getDestinations()} * @return {@code true} if this processor already contains the incoming processor as its destination, {@code false} if not */ public boolean containsDestination(NifiVisitableProcessor parent) { final String thisId = getDto().getId(); final String parentId = parent.getDto().getId(); NifiVisitableProcessor p = Iterables.tryFind(getDestinations(), new Predicate<NifiVisitableProcessor>() { @Override public boolean apply(NifiVisitableProcessor nifiVisitableProcessor) { return nifiVisitableProcessor.getDto().getId().equalsIgnoreCase(thisId) || nifiVisitableProcessor.getDto().getId() .equalsIgnoreCase(parentId); } }).orNull(); return p != null; } /** * Return all the processors including the destinations walking thr graph of the {@link NifiVisitableProcessor#getDestinations()} * * @return all the processors including the destinations walking thr graph of the {@link NifiVisitableProcessor#getDestinations()} */ public Set<ProcessorDTO> getProcessors() { return getProcessors(null); } /** * Return all the processors including the destinations walking thr graph of the {@link NifiVisitableProcessor#getDestinations()} * * @param set of processors to inspect and retreive the NiFi processor dto from * @return all the processors including the destinations walking thr graph of the {@link NifiVisitableProcessor#getDestinations()} */ public Set<ProcessorDTO> getProcessors(Set<NifiVisitableProcessor> set) { if (set == null) { set = new HashSet<>(); } set.add(this); for (NifiVisitableProcessor child : getDestinations()) { if (!set.contains(child)) { child.getProcessors(set); } } Set<ProcessorDTO> p = new HashSet<>(); for (NifiVisitableProcessor x : set) { p.add(x.getDto()); } return p; } /** * Return the id for this processor * * @return the id for the processor */ public String getId() { return id; } /** * add a connection as a source connection * * @param conn the source connection to this processor */ public void addSourceConnectionIdentifier(ConnectionDTO conn) { getSourceConnectionIdentifiers().add(new NiFiFlowProcessorConnection(conn.getId(), conn.getName(), conn.getSelectedRelationships())); } /** * add a connectionas a destination connection * * @param conn the destination connection from this processor */ public void addDestinationConnectionIdentifier(ConnectionDTO conn) { NiFiFlowProcessorConnection destinationConnection = new NiFiFlowProcessorConnection(conn.getId(), conn.getName(), conn.getSelectedRelationships()); getDestinationConnectionIdentifiers().add(destinationConnection); } /** * Return all connection ids marked as sources coming to this processor * * @return all connection ids marked as sources coming to this processor */ public Set<NiFiFlowProcessorConnection> getSourceConnectionIdentifiers() { if (sourceConnectionIdentifiers == null) { sourceConnectionIdentifiers = new HashSet<>(); } return sourceConnectionIdentifiers; } /** * Return all connection ids marked as destinations from this processor * * @return all connection ids marked as destinations from this processor */ public Set<NiFiFlowProcessorConnection> getDestinationConnectionIdentifiers() { if (destinationConnectionIdentifiers == null) { destinationConnectionIdentifiers = new HashSet<>(); } return destinationConnectionIdentifiers; } }