private FlowSnippetDTO copyContentsForGroup()

in nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java [505:803]


    private FlowSnippetDTO copyContentsForGroup(final FlowSnippetDTO snippetContents, final String groupId, final Map<String, ConnectableDTO> parentConnectableMap,
                                                Map<String, String> serviceIdMap, final String idGenerationSeed, boolean isCopy) {

        final FlowSnippetDTO snippetContentsCopy = new FlowSnippetDTO();
        try {
            //
            // Copy the Controller Services
            //
            if (serviceIdMap == null) {
                serviceIdMap = new HashMap<>();
            }

            final Set<ControllerServiceDTO> services = new HashSet<>();
            if (snippetContents.getControllerServices() != null) {
                for (final ControllerServiceDTO serviceDTO : snippetContents.getControllerServices()) {
                    final ControllerServiceDTO service = dtoFactory.copy(serviceDTO);
                    service.setId(generateId(serviceDTO.getId(), idGenerationSeed, isCopy));
                    service.setState(ControllerServiceState.DISABLED.name());
                    services.add(service);

                    // Map old service ID to new service ID so that we can make sure that we reference the new ones.
                    serviceIdMap.put(serviceDTO.getId(), service.getId());

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.ControllerService, serviceDTO.getId(), serviceDTO.getName()),
                                ResourceFactory.getComponentResource(ResourceType.ControllerService, service.getId(), service.getName()), idGenerationSeed);
                    }
                }
            }

            // if there is any controller service that maps to another controller service, update the id's
            for (final ControllerServiceDTO serviceDTO : services) {
                final Map<String, String> properties = serviceDTO.getProperties();
                final Map<String, PropertyDescriptorDTO> descriptors = serviceDTO.getDescriptors();
                if (properties != null && descriptors != null) {
                    for (final PropertyDescriptorDTO descriptor : descriptors.values()) {
                        if (descriptor.getIdentifiesControllerService() != null) {
                            final String currentServiceId = properties.get(descriptor.getName());
                            if (currentServiceId == null) {
                                continue;
                            }

                            final String newServiceId = serviceIdMap.get(currentServiceId);

                            // If there is no new Controller Service ID, leave it to set to whatever it was. This was either an invalid reference
                            // to begin with, or was a reference to a higher-level Controller Service, in which case the id shouldn't change.
                            if (newServiceId != null) {
                                properties.put(descriptor.getName(), newServiceId);
                            }
                        }
                    }
                }
            }
            snippetContentsCopy.setControllerServices(services);

            //
            // Copy the labels
            //
            final Set<LabelDTO> labels = new HashSet<>();
            if (snippetContents.getLabels() != null) {
                for (final LabelDTO labelDTO : snippetContents.getLabels()) {
                    final LabelDTO label = dtoFactory.copy(labelDTO);
                    label.setId(generateId(labelDTO.getId(), idGenerationSeed, isCopy));
                    label.setParentGroupId(groupId);
                    labels.add(label);

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.Label, labelDTO.getId(), labelDTO.getLabel()),
                                ResourceFactory.getComponentResource(ResourceType.Label, label.getId(), label.getLabel()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setLabels(labels);

            //
            // Copy connectable components
            //
            // maps a group ID-ID of a Connectable in the template to the new instance
            final Map<String, ConnectableDTO> connectableMap = new HashMap<>();

            //
            // Copy the funnels
            //
            final Set<FunnelDTO> funnels = new HashSet<>();
            if (snippetContents.getFunnels() != null) {
                for (final FunnelDTO funnelDTO : snippetContents.getFunnels()) {
                    final FunnelDTO cp = dtoFactory.copy(funnelDTO);
                    cp.setId(generateId(funnelDTO.getId(), idGenerationSeed, isCopy));
                    cp.setParentGroupId(groupId);
                    funnels.add(cp);

                    connectableMap.put(funnelDTO.getParentGroupId() + "-" + funnelDTO.getId(), dtoFactory.createConnectableDto(cp));

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.Funnel, funnelDTO.getId(), funnelDTO.getId()),
                                ResourceFactory.getComponentResource(ResourceType.Funnel, cp.getId(), cp.getId()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setFunnels(funnels);

            final Set<PortDTO> inputPorts = new HashSet<>();
            if (snippetContents.getInputPorts() != null) {
                for (final PortDTO portDTO : snippetContents.getInputPorts()) {
                    final PortDTO cp = dtoFactory.copy(portDTO);
                    cp.setId(generateId(portDTO.getId(), idGenerationSeed, isCopy));
                    cp.setParentGroupId(groupId);
                    if (portDTO.getState() != null && portDTO.getState().equals(ScheduledState.DISABLED.toString())) {
                        cp.setState(ScheduledState.DISABLED.toString());
                    } else {
                        cp.setState(ScheduledState.STOPPED.toString());
                    }
                    inputPorts.add(cp);

                    final ConnectableDTO portConnectable = dtoFactory.createConnectableDto(cp, ConnectableType.INPUT_PORT);
                    connectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
                    if (parentConnectableMap != null) {
                        parentConnectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
                    }

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.InputPort, portDTO.getId(), portDTO.getName()),
                                ResourceFactory.getComponentResource(ResourceType.InputPort, cp.getId(), cp.getName()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setInputPorts(inputPorts);

            final Set<PortDTO> outputPorts = new HashSet<>();
            if (snippetContents.getOutputPorts() != null) {
                for (final PortDTO portDTO : snippetContents.getOutputPorts()) {
                    final PortDTO cp = dtoFactory.copy(portDTO);
                    cp.setId(generateId(portDTO.getId(), idGenerationSeed, isCopy));
                    cp.setParentGroupId(groupId);
                    if (portDTO.getState() != null && portDTO.getState().equals(ScheduledState.DISABLED.toString())) {
                        cp.setState(ScheduledState.DISABLED.toString());
                    } else {
                        cp.setState(ScheduledState.STOPPED.toString());
                    }
                    outputPorts.add(cp);

                    final ConnectableDTO portConnectable = dtoFactory.createConnectableDto(cp, ConnectableType.OUTPUT_PORT);
                    connectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
                    if (parentConnectableMap != null) {
                        parentConnectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
                    }

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.OutputPort, portDTO.getId(), portDTO.getName()),
                                ResourceFactory.getComponentResource(ResourceType.OutputPort, cp.getId(), cp.getName()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setOutputPorts(outputPorts);

            //
            // Copy the processors
            //
            final Set<ProcessorDTO> processors = new HashSet<>();
            if (snippetContents.getProcessors() != null) {
                for (final ProcessorDTO processorDTO : snippetContents.getProcessors()) {
                    final ProcessorDTO cp = dtoFactory.copy(processorDTO);
                    cp.setId(generateId(processorDTO.getId(), idGenerationSeed, isCopy));
                    cp.setParentGroupId(groupId);
                    if (processorDTO.getState() != null && processorDTO.getState().equals(ScheduledState.DISABLED.toString())) {
                        cp.setState(ScheduledState.DISABLED.toString());
                    } else {
                        cp.setState(ScheduledState.STOPPED.toString());
                    }
                    processors.add(cp);

                    connectableMap.put(processorDTO.getParentGroupId() + "-" + processorDTO.getId(), dtoFactory.createConnectableDto(cp));

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.Processor, processorDTO.getId(), processorDTO.getName()),
                                ResourceFactory.getComponentResource(ResourceType.Processor, cp.getId(), cp.getName()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setProcessors(processors);

            // if there is any controller service that maps to another controller service, update the id's
            updateControllerServiceIdentifiers(snippetContentsCopy, serviceIdMap);

            //
            // Copy ProcessGroups
            //
            // instantiate the process groups, renaming as necessary
            final Set<ProcessGroupDTO> groups = new HashSet<>();
            if (snippetContents.getProcessGroups() != null) {
                for (final ProcessGroupDTO groupDTO : snippetContents.getProcessGroups()) {
                    final ProcessGroupDTO cp = dtoFactory.copy(groupDTO, false);
                    cp.setId(generateId(groupDTO.getId(), idGenerationSeed, isCopy));
                    cp.setParentGroupId(groupId);

                    // copy the contents of this group - we do not copy via the dto factory since we want to specify new ids
                    final FlowSnippetDTO contentsCopy = copyContentsForGroup(groupDTO.getContents(), cp.getId(), connectableMap, serviceIdMap, idGenerationSeed, isCopy);
                    cp.setContents(contentsCopy);
                    groups.add(cp);

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.ProcessGroup, groupDTO.getId(), groupDTO.getName()),
                                ResourceFactory.getComponentResource(ResourceType.ProcessGroup, cp.getId(), cp.getName()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setProcessGroups(groups);

            final Set<RemoteProcessGroupDTO> remoteGroups = new HashSet<>();
            if (snippetContents.getRemoteProcessGroups() != null) {
                for (final RemoteProcessGroupDTO remoteGroupDTO : snippetContents.getRemoteProcessGroups()) {
                    final RemoteProcessGroupDTO cp = dtoFactory.copy(remoteGroupDTO);
                    cp.setId(generateId(remoteGroupDTO.getId(), idGenerationSeed, isCopy));
                    cp.setParentGroupId(groupId);

                    final RemoteProcessGroupContentsDTO contents = cp.getContents();
                    if (contents != null && contents.getInputPorts() != null) {
                        for (final RemoteProcessGroupPortDTO remotePort : contents.getInputPorts()) {
                            remotePort.setGroupId(cp.getId());
                            final String originalId = remotePort.getId();
                            if (remotePort.getTargetId() == null) {
                                remotePort.setTargetId(originalId);
                            }
                            remotePort.setId(generateId(remotePort.getId(), idGenerationSeed, isCopy));

                            connectableMap.put(remoteGroupDTO.getId() + "-" + originalId, dtoFactory.createConnectableDto(remotePort, ConnectableType.REMOTE_INPUT_PORT));
                        }
                    }
                    if (contents != null && contents.getOutputPorts() != null) {
                        for (final RemoteProcessGroupPortDTO remotePort : contents.getOutputPorts()) {
                            remotePort.setGroupId(cp.getId());
                            final String originalId = remotePort.getId();
                            if (remotePort.getTargetId() == null) {
                                remotePort.setTargetId(originalId);
                            }
                            remotePort.setId(generateId(remotePort.getId(), idGenerationSeed, isCopy));
                            connectableMap.put(remoteGroupDTO.getId() + "-" + originalId, dtoFactory.createConnectableDto(remotePort, ConnectableType.REMOTE_OUTPUT_PORT));
                        }
                    }

                    remoteGroups.add(cp);

                    // clone policies as appropriate
                    if (isCopy) {
                        cloneComponentSpecificPolicies(
                                ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, remoteGroupDTO.getId(), remoteGroupDTO.getName()),
                                ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, cp.getId(), cp.getName()), idGenerationSeed);
                    }
                }
            }
            snippetContentsCopy.setRemoteProcessGroups(remoteGroups);

            final Set<ConnectionDTO> connections = new HashSet<>();
            if (snippetContents.getConnections() != null) {
                for (final ConnectionDTO connectionDTO : snippetContents.getConnections()) {
                    final ConnectionDTO cp = dtoFactory.copy(connectionDTO);

                    final ConnectableDTO source = connectableMap.get(cp.getSource().getGroupId() + "-" + cp.getSource().getId());
                    final ConnectableDTO destination = connectableMap.get(cp.getDestination().getGroupId() + "-" + cp.getDestination().getId());

                    // ensure all referenced components are present
                    if (source == null || destination == null) {
                        throw new IllegalArgumentException("The flow snippet contains a Connection that references a component that is not included.");
                    }

                    cp.setId(generateId(connectionDTO.getId(), idGenerationSeed, isCopy));
                    cp.setSource(source);
                    cp.setDestination(destination);
                    cp.setParentGroupId(groupId);
                    connections.add(cp);

                    // note - no need to copy policies of a connection as their permissions are inferred through the source and destination
                }
            }
            snippetContentsCopy.setConnections(connections);

            return snippetContentsCopy;
        } catch (Exception e) {
            // attempt to role back any policies of the copies that were created in preparation for the clone
            rollbackClonedPolicies(snippetContentsCopy);

            // rethrow the original exception
            throw e;
        }
    }