/*
 * 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.nifi.web.api.dto;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.action.Action;
import org.apache.nifi.action.component.details.ComponentDetails;
import org.apache.nifi.action.component.details.ExtensionDetails;
import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
import org.apache.nifi.action.component.details.FlowChangeRemoteProcessGroupDetails;
import org.apache.nifi.action.component.details.RemoteProcessGroupDetails;
import org.apache.nifi.action.details.ActionDetails;
import org.apache.nifi.action.details.ConfigureDetails;
import org.apache.nifi.action.details.ConnectDetails;
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
import org.apache.nifi.action.details.FlowChangeConnectDetails;
import org.apache.nifi.action.details.FlowChangeMoveDetails;
import org.apache.nifi.action.details.FlowChangePurgeDetails;
import org.apache.nifi.action.details.MoveDetails;
import org.apache.nifi.action.details.PurgeDetails;
import org.apache.nifi.annotation.behavior.Restricted;
import org.apache.nifi.annotation.behavior.Restriction;
import org.apache.nifi.annotation.behavior.Stateful;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.DeprecationNotice;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.authorization.AccessPolicy;
import org.apache.nifi.authorization.Authorizer;
import org.apache.nifi.authorization.AuthorizerCapabilityDetection;
import org.apache.nifi.authorization.Group;
import org.apache.nifi.authorization.RequestAction;
import org.apache.nifi.authorization.Resource;
import org.apache.nifi.authorization.User;
import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.resource.ComponentAuthorizable;
import org.apache.nifi.authorization.resource.OperationAuthorizable;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.bundle.BundleCoordinate;
import org.apache.nifi.bundle.BundleDetails;
import org.apache.nifi.cluster.coordination.heartbeat.NodeHeartbeat;
import org.apache.nifi.cluster.coordination.node.NodeConnectionStatus;
import org.apache.nifi.cluster.event.NodeEvent;
import org.apache.nifi.cluster.manager.StatusMerger;
import org.apache.nifi.cluster.protocol.NodeIdentifier;
import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.PropertyDependency;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.components.state.Scope;
import org.apache.nifi.components.state.StateMap;
import org.apache.nifi.components.validation.ValidationState;
import org.apache.nifi.components.validation.ValidationStatus;
import org.apache.nifi.connectable.Connectable;
import org.apache.nifi.connectable.ConnectableType;
import org.apache.nifi.connectable.Connection;
import org.apache.nifi.connectable.Funnel;
import org.apache.nifi.connectable.Port;
import org.apache.nifi.connectable.Position;
import org.apache.nifi.controller.ActiveThreadInfo;
import org.apache.nifi.controller.ComponentNode;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.Counter;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.ReportingTaskNode;
import org.apache.nifi.controller.Snippet;
import org.apache.nifi.controller.Template;
import org.apache.nifi.controller.ThreadDetails;
import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.controller.label.Label;
import org.apache.nifi.controller.queue.DropFlowFileState;
import org.apache.nifi.controller.queue.DropFlowFileStatus;
import org.apache.nifi.controller.queue.FlowFileQueue;
import org.apache.nifi.controller.queue.FlowFileSummary;
import org.apache.nifi.controller.queue.ListFlowFileState;
import org.apache.nifi.controller.queue.ListFlowFileStatus;
import org.apache.nifi.controller.queue.LoadBalanceStrategy;
import org.apache.nifi.controller.queue.LocalQueuePartitionDiagnostics;
import org.apache.nifi.controller.queue.QueueDiagnostics;
import org.apache.nifi.controller.queue.QueueSize;
import org.apache.nifi.controller.queue.RemoteQueuePartitionDiagnostics;
import org.apache.nifi.controller.repository.FlowFileRecord;
import org.apache.nifi.controller.repository.claim.ContentClaim;
import org.apache.nifi.controller.repository.claim.ResourceClaim;
import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.controller.service.ControllerServiceProvider;
import org.apache.nifi.controller.state.SortedStateUtils;
import org.apache.nifi.controller.status.ConnectionStatus;
import org.apache.nifi.controller.status.PortStatus;
import org.apache.nifi.controller.status.ProcessGroupStatus;
import org.apache.nifi.controller.status.ProcessorStatus;
import org.apache.nifi.controller.status.RemoteProcessGroupStatus;
import org.apache.nifi.controller.status.analytics.ConnectionStatusPredictions;
import org.apache.nifi.controller.status.analytics.StatusAnalytics;
import org.apache.nifi.controller.status.history.GarbageCollectionHistory;
import org.apache.nifi.controller.status.history.GarbageCollectionStatus;
import org.apache.nifi.diagnostics.GarbageCollection;
import org.apache.nifi.diagnostics.StorageUsage;
import org.apache.nifi.diagnostics.SystemDiagnostics;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.flowfile.FlowFilePrioritizer;
import org.apache.nifi.flowfile.attributes.CoreAttributes;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.ProcessGroupCounts;
import org.apache.nifi.groups.RemoteProcessGroup;
import org.apache.nifi.groups.RemoteProcessGroupCounts;
import org.apache.nifi.history.History;
import org.apache.nifi.nar.ExtensionDefinition;
import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.nar.NarClassLoadersHolder;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterDescriptor;
import org.apache.nifi.parameter.ParameterReferenceManager;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.provenance.lineage.ComputeLineageResult;
import org.apache.nifi.provenance.lineage.ComputeLineageSubmission;
import org.apache.nifi.provenance.lineage.LineageEdge;
import org.apache.nifi.provenance.lineage.LineageNode;
import org.apache.nifi.provenance.lineage.ProvenanceEventLineageNode;
import org.apache.nifi.registry.ComponentVariableRegistry;
import org.apache.nifi.registry.VariableDescriptor;
import org.apache.nifi.registry.flow.FlowRegistry;
import org.apache.nifi.registry.flow.VersionControlInformation;
import org.apache.nifi.registry.flow.VersionedComponent;
import org.apache.nifi.registry.flow.VersionedFlowState;
import org.apache.nifi.registry.flow.VersionedFlowStatus;
import org.apache.nifi.registry.flow.VersionedProcessGroup;
import org.apache.nifi.registry.flow.diff.DifferenceType;
import org.apache.nifi.registry.flow.diff.FlowComparison;
import org.apache.nifi.registry.flow.diff.FlowDifference;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedComponent;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedConnection;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedControllerService;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedFunnel;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedLabel;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedPort;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedProcessGroup;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedProcessor;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedRemoteGroupPort;
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedRemoteProcessGroup;
import org.apache.nifi.registry.variable.VariableRegistryUpdateRequest;
import org.apache.nifi.registry.variable.VariableRegistryUpdateStep;
import org.apache.nifi.remote.PublicPort;
import org.apache.nifi.remote.RemoteGroupPort;
import org.apache.nifi.reporting.Bulletin;
import org.apache.nifi.reporting.BulletinRepository;
import org.apache.nifi.reporting.ReportingTask;
import org.apache.nifi.scheduling.SchedulingStrategy;
import org.apache.nifi.util.FlowDifferenceFilters;
import org.apache.nifi.util.FormatUtils;
import org.apache.nifi.web.FlowModification;
import org.apache.nifi.web.Revision;
import org.apache.nifi.web.api.dto.action.ActionDTO;
import org.apache.nifi.web.api.dto.action.HistoryDTO;
import org.apache.nifi.web.api.dto.action.component.details.ComponentDetailsDTO;
import org.apache.nifi.web.api.dto.action.component.details.ExtensionDetailsDTO;
import org.apache.nifi.web.api.dto.action.component.details.RemoteProcessGroupDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.ActionDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.ConfigureDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.ConnectDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.MoveDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.PurgeDetailsDTO;
import org.apache.nifi.web.api.dto.diagnostics.ClassLoaderDiagnosticsDTO;
import org.apache.nifi.web.api.dto.diagnostics.ConnectionDiagnosticsDTO;
import org.apache.nifi.web.api.dto.diagnostics.ConnectionDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.diagnostics.ControllerServiceDiagnosticsDTO;
import org.apache.nifi.web.api.dto.diagnostics.GCDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.diagnostics.GarbageCollectionDiagnosticsDTO;
import org.apache.nifi.web.api.dto.diagnostics.JVMControllerDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.diagnostics.JVMDiagnosticsDTO;
import org.apache.nifi.web.api.dto.diagnostics.JVMDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.diagnostics.JVMFlowDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.diagnostics.JVMSystemDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.diagnostics.LocalQueuePartitionDTO;
import org.apache.nifi.web.api.dto.diagnostics.ProcessorDiagnosticsDTO;
import org.apache.nifi.web.api.dto.diagnostics.RemoteQueuePartitionDTO;
import org.apache.nifi.web.api.dto.diagnostics.RepositoryUsageDTO;
import org.apache.nifi.web.api.dto.diagnostics.ThreadDumpDTO;
import org.apache.nifi.web.api.dto.flow.FlowBreadcrumbDTO;
import org.apache.nifi.web.api.dto.flow.FlowDTO;
import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO;
import org.apache.nifi.web.api.dto.provenance.lineage.LineageDTO;
import org.apache.nifi.web.api.dto.provenance.lineage.LineageRequestDTO;
import org.apache.nifi.web.api.dto.provenance.lineage.LineageRequestDTO.LineageRequestType;
import org.apache.nifi.web.api.dto.provenance.lineage.LineageResultsDTO;
import org.apache.nifi.web.api.dto.provenance.lineage.ProvenanceLinkDTO;
import org.apache.nifi.web.api.dto.provenance.lineage.ProvenanceNodeDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatisticsDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatisticsSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatusDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatusPredictionsSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.PortStatusDTO;
import org.apache.nifi.web.api.dto.status.PortStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO;
import org.apache.nifi.web.api.dto.status.ProcessGroupStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO;
import org.apache.nifi.web.api.dto.status.ProcessorStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO;
import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusSnapshotDTO;
import org.apache.nifi.web.api.entity.AccessPolicyEntity;
import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity;
import org.apache.nifi.web.api.entity.AffectedComponentEntity;
import org.apache.nifi.web.api.entity.AllowableValueEntity;
import org.apache.nifi.web.api.entity.BulletinEntity;
import org.apache.nifi.web.api.entity.ComponentReferenceEntity;
import org.apache.nifi.web.api.entity.ConnectionStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ControllerServiceEntity;
import org.apache.nifi.web.api.entity.FlowBreadcrumbEntity;
import org.apache.nifi.web.api.entity.ParameterContextReferenceEntity;
import org.apache.nifi.web.api.entity.ParameterEntity;
import org.apache.nifi.web.api.entity.PortEntity;
import org.apache.nifi.web.api.entity.PortStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ProcessGroupEntity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.TenantEntity;
import org.apache.nifi.web.api.entity.VariableEntity;
import org.apache.nifi.web.controller.ControllerFacade;
import org.apache.nifi.web.revision.RevisionManager;

import javax.ws.rs.WebApplicationException;
import java.text.Collator;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public final class DtoFactory {

    @SuppressWarnings("rawtypes")
    private final static Comparator<Class> CLASS_NAME_COMPARATOR = new Comparator<Class>() {
        @Override
        public int compare(final Class class1, final Class class2) {
            return Collator.getInstance(Locale.US).compare(class1.getSimpleName(), class2.getSimpleName());
        }
    };
    public static final String SENSITIVE_VALUE_MASK = "********";

    private BulletinRepository bulletinRepository;
    private ControllerServiceProvider controllerServiceProvider;
    private EntityFactory entityFactory;
    private Authorizer authorizer;
    private ExtensionManager extensionManager;

    public ControllerConfigurationDTO createControllerConfigurationDto(final ControllerFacade controllerFacade) {
        final ControllerConfigurationDTO dto = new ControllerConfigurationDTO();
        dto.setMaxTimerDrivenThreadCount(controllerFacade.getMaxTimerDrivenThreadCount());
        dto.setMaxEventDrivenThreadCount(controllerFacade.getMaxEventDrivenThreadCount());
        return dto;
    }

    public FlowConfigurationDTO createFlowConfigurationDto(final String autoRefreshInterval,
                                                           final Long defaultBackPressureObjectThreshold,
                                                           final String defaultBackPressureDataSizeThreshold) {
        final FlowConfigurationDTO dto = new FlowConfigurationDTO();

        // get the refresh interval
        final long refreshInterval = FormatUtils.getTimeDuration(autoRefreshInterval, TimeUnit.SECONDS);
        dto.setAutoRefreshIntervalSeconds(refreshInterval);
        dto.setSupportsManagedAuthorizer(AuthorizerCapabilityDetection.isManagedAuthorizer(authorizer));
        dto.setSupportsConfigurableUsersAndGroups(AuthorizerCapabilityDetection.isConfigurableUserGroupProvider(authorizer));
        dto.setSupportsConfigurableAuthorizer(AuthorizerCapabilityDetection.isConfigurableAccessPolicyProvider(authorizer));

        final Date now = new Date();
        dto.setTimeOffset(TimeZone.getDefault().getOffset(now.getTime()));
        dto.setCurrentTime(now);

        dto.setDefaultBackPressureDataSizeThreshold(defaultBackPressureDataSizeThreshold);
        dto.setDefaultBackPressureObjectThreshold(defaultBackPressureObjectThreshold);

        return dto;
    }

    /**
     * Creates an ActionDTO for the specified Action.
     *
     * @param action action
     * @return dto
     */
    public ActionDTO createActionDto(final Action action) {
        final ActionDTO actionDto = new ActionDTO();
        actionDto.setId(action.getId());
        actionDto.setSourceId(action.getSourceId());
        actionDto.setSourceName(action.getSourceName());
        actionDto.setSourceType(action.getSourceType().toString());
        actionDto.setTimestamp(action.getTimestamp());
        actionDto.setUserIdentity(action.getUserIdentity());
        actionDto.setOperation(action.getOperation().toString());
        actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails()));
        actionDto.setComponentDetails(createComponentDetailsDto(action.getComponentDetails()));

        return actionDto;
    }

    /**
     * Creates an ActionDetailsDTO for the specified ActionDetails.
     *
     * @param actionDetails details
     * @return dto
     */
    private ActionDetailsDTO createActionDetailsDto(final ActionDetails actionDetails) {
        if (actionDetails == null) {
            return null;
        }

        if (actionDetails instanceof FlowChangeConfigureDetails) {
            final ConfigureDetailsDTO configureDetails = new ConfigureDetailsDTO();
            configureDetails.setName(((ConfigureDetails) actionDetails).getName());
            configureDetails.setPreviousValue(((ConfigureDetails) actionDetails).getPreviousValue());
            configureDetails.setValue(((ConfigureDetails) actionDetails).getValue());
            return configureDetails;
        } else if (actionDetails instanceof FlowChangeConnectDetails) {
            final ConnectDetailsDTO connectDetails = new ConnectDetailsDTO();
            connectDetails.setSourceId(((ConnectDetails) actionDetails).getSourceId());
            connectDetails.setSourceName(((ConnectDetails) actionDetails).getSourceName());
            connectDetails.setSourceType(((ConnectDetails) actionDetails).getSourceType().toString());
            connectDetails.setRelationship(((ConnectDetails) actionDetails).getRelationship());
            connectDetails.setDestinationId(((ConnectDetails) actionDetails).getDestinationId());
            connectDetails.setDestinationName(((ConnectDetails) actionDetails).getDestinationName());
            connectDetails.setDestinationType(((ConnectDetails) actionDetails).getDestinationType().toString());
            return connectDetails;
        } else if (actionDetails instanceof FlowChangeMoveDetails) {
            final MoveDetailsDTO moveDetails = new MoveDetailsDTO();
            moveDetails.setPreviousGroup(((MoveDetails) actionDetails).getPreviousGroup());
            moveDetails.setPreviousGroupId(((MoveDetails) actionDetails).getPreviousGroupId());
            moveDetails.setGroup(((MoveDetails) actionDetails).getGroup());
            moveDetails.setGroupId(((MoveDetails) actionDetails).getGroupId());
            return moveDetails;
        } else if (actionDetails instanceof FlowChangePurgeDetails) {
            final PurgeDetailsDTO purgeDetails = new PurgeDetailsDTO();
            purgeDetails.setEndDate(((PurgeDetails) actionDetails).getEndDate());
            return purgeDetails;
        } else {
            throw new WebApplicationException(new IllegalArgumentException(String.format("Unrecognized type of action details encountered %s during serialization.", actionDetails.toString())));
        }
    }

    /**
     * Creates a ComponentDetailsDTO for the specified ComponentDetails.
     *
     * @param componentDetails details
     * @return dto
     */
    private ComponentDetailsDTO createComponentDetailsDto(final ComponentDetails componentDetails) {
        if (componentDetails == null) {
            return null;
        }

        if (componentDetails instanceof FlowChangeExtensionDetails) {
            final ExtensionDetailsDTO processorDetails = new ExtensionDetailsDTO();
            processorDetails.setType(((ExtensionDetails) componentDetails).getType());
            return processorDetails;
        } else if (componentDetails instanceof FlowChangeRemoteProcessGroupDetails) {
            final RemoteProcessGroupDetailsDTO remoteProcessGroupDetails = new RemoteProcessGroupDetailsDTO();
            remoteProcessGroupDetails.setUri(((RemoteProcessGroupDetails) componentDetails).getUri());
            return remoteProcessGroupDetails;
        } else {
            throw new WebApplicationException(new IllegalArgumentException(String.format("Unrecognized type of component details encountered %s during serialization. ", componentDetails.toString())));
        }
    }

    /**
     * Creates a HistoryDTO from the specified History.
     *
     * @param history history
     * @return dto
     */
    public HistoryDTO createHistoryDto(final History history) {
        final HistoryDTO historyDto = new HistoryDTO();
        historyDto.setTotal(history.getTotal());
        historyDto.setLastRefreshed(history.getLastRefreshed());
        return historyDto;
    }

    /**
     * Creates a ComponentStateDTO for the given component and state's.
     *
     * @param componentId component id
     * @param localState local state
     * @param clusterState cluster state
     * @return dto
     */
    public ComponentStateDTO createComponentStateDTO(final String componentId, final Class<?> componentClass, final StateMap localState, final StateMap clusterState) {
        final ComponentStateDTO dto = new ComponentStateDTO();
        dto.setComponentId(componentId);
        dto.setStateDescription(getStateDescription(componentClass));
        dto.setLocalState(createStateMapDTO(Scope.LOCAL, localState));
        dto.setClusterState(createStateMapDTO(Scope.CLUSTER, clusterState));
        return dto;
    }

    /**
     * Gets the description of the state this component persists.
     *
     * @param componentClass the component class
     * @return state description
     */
    private String getStateDescription(final Class<?> componentClass) {
        final Stateful capabilityDesc = componentClass.getAnnotation(Stateful.class);
        if (capabilityDesc != null) {
            return capabilityDesc.description();
        } else {
            return null;
        }
    }

    /**
     * Creates a StateMapDTO for the given scope and state map.
     *
     * @param scope the scope
     * @param stateMap the state map
     * @return dto
     */
    public StateMapDTO createStateMapDTO(final Scope scope, final StateMap stateMap) {
        if (stateMap == null) {
            return null;
        }

        final StateMapDTO dto = new StateMapDTO();
        dto.setScope(scope.toString());

        final TreeMap<String, String> sortedState = new TreeMap<>(SortedStateUtils.getKeyComparator());
        final Map<String, String> state = stateMap.toMap();
        sortedState.putAll(state);

        int count = 0;
        final List<StateEntryDTO> stateEntries = new ArrayList<>();
        final Set<Map.Entry<String, String>> entrySet = sortedState.entrySet();
        for (final Iterator<Entry<String, String>> iter = entrySet.iterator(); iter.hasNext() && count++ < SortedStateUtils.MAX_COMPONENT_STATE_ENTRIES;) {
            final Map.Entry<String, String> entry = iter.next();
            final StateEntryDTO entryDTO = new StateEntryDTO();
            entryDTO.setKey(entry.getKey());
            entryDTO.setValue(entry.getValue());
            stateEntries.add(entryDTO);
        }
        dto.setTotalEntryCount(state.size());
        dto.setState(stateEntries);

        return dto;
    }

    /**
     * Creates CounterDTOs for each Counter specified.
     *
     * @param counterDtos dtos
     * @return dto
     */
    public CountersSnapshotDTO createCountersDto(final Collection<CounterDTO> counterDtos) {
        final CountersSnapshotDTO dto = new CountersSnapshotDTO();
        dto.setCounters(counterDtos);
        dto.setGenerated(new Date());
        return dto;
    }

    /**
     * Creates a CounterDTO from the specified Counter.
     *
     * @param counter counter
     * @return dto
     */
    public CounterDTO createCounterDto(final Counter counter) {
        final CounterDTO dto = new CounterDTO();
        dto.setId(counter.getIdentifier());
        dto.setContext(counter.getContext());
        dto.setName(counter.getName());
        dto.setValueCount(counter.getValue());
        dto.setValue(FormatUtils.formatCount(counter.getValue()));
        return dto;
    }

    /**
     * Creates a PositionDTO from the specified position
     *
     * @param position position
     * @return dto
     */
    public PositionDTO createPositionDto(final Position position) {
        return new PositionDTO(position.getX(), position.getY());
    }

    private boolean isDropRequestComplete(final DropFlowFileState state) {
        return DropFlowFileState.COMPLETE.equals(state) || DropFlowFileState.CANCELED.equals(state) || DropFlowFileState.FAILURE.equals(state);
    }

    /**
     * Creates a DropRequestDTO from the specified flow file status.
     *
     * @param dropRequest dropRequest
     * @return dto
     */
    public DropRequestDTO createDropRequestDTO(final DropFlowFileStatus dropRequest) {
        final DropRequestDTO dto = new DropRequestDTO();
        dto.setId(dropRequest.getRequestIdentifier());
        dto.setSubmissionTime(new Date(dropRequest.getRequestSubmissionTime()));
        dto.setLastUpdated(new Date(dropRequest.getLastUpdated()));
        dto.setState(dropRequest.getState().toString());
        dto.setFailureReason(dropRequest.getFailureReason());
        dto.setFinished(isDropRequestComplete(dropRequest.getState()));

        final QueueSize dropped = dropRequest.getDroppedSize();
        dto.setDroppedCount(dropped.getObjectCount());
        dto.setDroppedSize(dropped.getByteCount());
        dto.setDropped(FormatUtils.formatCount(dropped.getObjectCount()) + " / " + FormatUtils.formatDataSize(dropped.getByteCount()));

        final QueueSize current = dropRequest.getCurrentSize();
        dto.setCurrentCount(current.getObjectCount());
        dto.setCurrentSize(current.getByteCount());
        dto.setCurrent(FormatUtils.formatCount(current.getObjectCount()) + " / " + FormatUtils.formatDataSize(current.getByteCount()));

        final QueueSize original = dropRequest.getOriginalSize();
        dto.setOriginalCount(original.getObjectCount());
        dto.setOriginalSize(original.getByteCount());
        dto.setOriginal(FormatUtils.formatCount(original.getObjectCount()) + " / " + FormatUtils.formatDataSize(original.getByteCount()));

        if (isDropRequestComplete(dropRequest.getState())) {
            dto.setPercentCompleted(100);
        } else {
            dto.setPercentCompleted((dropped.getObjectCount() * 100) / original.getObjectCount());
        }

        return dto;
    }

    private boolean isListingRequestComplete(final ListFlowFileState state) {
        return ListFlowFileState.COMPLETE.equals(state) || ListFlowFileState.CANCELED.equals(state) || ListFlowFileState.FAILURE.equals(state);
    }

    private QueueSizeDTO createQueueSizeDTO(final QueueSize queueSize) {
        final QueueSizeDTO dto = new QueueSizeDTO();
        dto.setByteCount(queueSize.getByteCount());
        dto.setObjectCount(queueSize.getObjectCount());
        return dto;
    }

    /**
     * Creates a ListingRequestDTO from the specified ListFlowFileStatus.
     *
     * @param listingRequest listingRequest
     * @return dto
     */
    public ListingRequestDTO createListingRequestDTO(final ListFlowFileStatus listingRequest) {
        final ListingRequestDTO dto = new ListingRequestDTO();
        dto.setId(listingRequest.getRequestIdentifier());
        dto.setSubmissionTime(new Date(listingRequest.getRequestSubmissionTime()));
        dto.setLastUpdated(new Date(listingRequest.getLastUpdated()));
        dto.setState(listingRequest.getState().toString());
        dto.setFailureReason(listingRequest.getFailureReason());
        dto.setFinished(isListingRequestComplete(listingRequest.getState()));
        dto.setMaxResults(listingRequest.getMaxResults());
        dto.setPercentCompleted(listingRequest.getCompletionPercentage());

        dto.setQueueSize(createQueueSizeDTO(listingRequest.getQueueSize()));

        if (isListingRequestComplete(listingRequest.getState())) {
            final List<FlowFileSummary> flowFileSummaries = listingRequest.getFlowFileSummaries();
            if (flowFileSummaries != null) {
                final Date now = new Date();
                final List<FlowFileSummaryDTO> summaryDtos = new ArrayList<>(flowFileSummaries.size());
                for (final FlowFileSummary summary : flowFileSummaries) {
                    summaryDtos.add(createFlowFileSummaryDTO(summary, now));
                }
                dto.setFlowFileSummaries(summaryDtos);
            }
        }

        return dto;
    }

    /**
     * Creates a FlowFileSummaryDTO from the specified FlowFileSummary.
     *
     * @param summary summary
     * @return dto
     */
    public FlowFileSummaryDTO createFlowFileSummaryDTO(final FlowFileSummary summary, final Date now) {
        final FlowFileSummaryDTO dto = new FlowFileSummaryDTO();
        dto.setUuid(summary.getUuid());
        dto.setFilename(summary.getFilename());

        dto.setPenalized(summary.isPenalized());
        final long penaltyExpiration = summary.getPenaltyExpirationMillis() - now.getTime();
        dto.setPenaltyExpiresIn(penaltyExpiration>=0?penaltyExpiration:0);

        dto.setPosition(summary.getPosition());
        dto.setSize(summary.getSize());

        final long queuedDuration = now.getTime() - summary.getLastQueuedTime();
        dto.setQueuedDuration(queuedDuration);

        final long age = now.getTime() - summary.getLineageStartDate();
        dto.setLineageDuration(age);

        return dto;
    }

    /**
     * Creates a FlowFileDTO from the specified FlowFileRecord.
     *
     * @param record record
     * @return dto
     */
    public FlowFileDTO createFlowFileDTO(final FlowFileRecord record) {
        final Date now = new Date();
        final FlowFileDTO dto = new FlowFileDTO();
        dto.setUuid(record.getAttribute(CoreAttributes.UUID.key()));
        dto.setFilename(record.getAttribute(CoreAttributes.FILENAME.key()));

        dto.setPenalized(record.isPenalized());
        final long penaltyExpiration = record.getPenaltyExpirationMillis() - now.getTime();
        dto.setPenaltyExpiresIn(penaltyExpiration>=0?penaltyExpiration:0);

        dto.setSize(record.getSize());
        dto.setAttributes(record.getAttributes());

        final long queuedDuration = now.getTime() - record.getLastQueueDate();
        dto.setQueuedDuration(queuedDuration);

        final long age = now.getTime() - record.getLineageStartDate();
        dto.setLineageDuration(age);

        final ContentClaim contentClaim = record.getContentClaim();
        if (contentClaim != null) {
            final ResourceClaim resourceClaim = contentClaim.getResourceClaim();
            dto.setContentClaimSection(resourceClaim.getSection());
            dto.setContentClaimContainer(resourceClaim.getContainer());
            dto.setContentClaimIdentifier(resourceClaim.getId());
            dto.setContentClaimOffset(contentClaim.getOffset() + record.getContentClaimOffset());
            dto.setContentClaimFileSizeBytes(record.getSize());
            dto.setContentClaimFileSize(FormatUtils.formatDataSize(record.getSize()));
        }

        return dto;
    }

    /**
     * Creates a ConnectionDTO from the specified Connection.
     *
     * @param connection connection
     * @return dto
     */
    public ConnectionDTO createConnectionDto(final Connection connection) {
        if (connection == null) {
            return null;
        }

        final ConnectionDTO dto = new ConnectionDTO();

        dto.setId(connection.getIdentifier());
        dto.setParentGroupId(connection.getProcessGroup().getIdentifier());

        final List<PositionDTO> bendPoints = new ArrayList<>();
        for (final Position bendPoint : connection.getBendPoints()) {
            bendPoints.add(createPositionDto(bendPoint));
        }
        dto.setBends(bendPoints);
        dto.setName(connection.getName());
        dto.setLabelIndex(connection.getLabelIndex());
        dto.setzIndex(connection.getZIndex());
        dto.setSource(createConnectableDto(connection.getSource()));
        dto.setDestination(createConnectableDto(connection.getDestination()));
        dto.setVersionedComponentId(connection.getVersionedComponentId().orElse(null));

        final FlowFileQueue flowFileQueue = connection.getFlowFileQueue();

        dto.setBackPressureObjectThreshold(flowFileQueue.getBackPressureObjectThreshold());
        dto.setBackPressureDataSizeThreshold(flowFileQueue.getBackPressureDataSizeThreshold());
        dto.setFlowFileExpiration(flowFileQueue.getFlowFileExpiration());
        dto.setPrioritizers(new ArrayList<String>());
        for (final FlowFilePrioritizer comparator : flowFileQueue.getPriorities()) {
            dto.getPrioritizers().add(comparator.getClass().getCanonicalName());
        }

        // For ports, we do not want to populate the relationships.
        for (final Relationship selectedRelationship : connection.getRelationships()) {
            if (!Relationship.ANONYMOUS.equals(selectedRelationship)) {
                if (dto.getSelectedRelationships() == null) {
                    dto.setSelectedRelationships(new TreeSet<String>(Collator.getInstance(Locale.US)));
                }

                dto.getSelectedRelationships().add(selectedRelationship.getName());
            }
        }

        // For ports, we do not want to populate the relationships.
        for (final Relationship availableRelationship : connection.getSource().getRelationships()) {
            if (!Relationship.ANONYMOUS.equals(availableRelationship)) {
                if (dto.getAvailableRelationships() == null) {
                    dto.setAvailableRelationships(new TreeSet<String>(Collator.getInstance(Locale.US)));
                }

                dto.getAvailableRelationships().add(availableRelationship.getName());
            }
        }

        final LoadBalanceStrategy loadBalanceStrategy = flowFileQueue.getLoadBalanceStrategy();
        dto.setLoadBalancePartitionAttribute(flowFileQueue.getPartitioningAttribute());
        dto.setLoadBalanceStrategy(loadBalanceStrategy.name());
        dto.setLoadBalanceCompression(flowFileQueue.getLoadBalanceCompression().name());

        if (loadBalanceStrategy == LoadBalanceStrategy.DO_NOT_LOAD_BALANCE) {
            dto.setLoadBalanceStatus(ConnectionDTO.LOAD_BALANCE_NOT_CONFIGURED);
        } else if (flowFileQueue.isActivelyLoadBalancing()) {
            dto.setLoadBalanceStatus(ConnectionDTO.LOAD_BALANCE_ACTIVE);
        } else {
            dto.setLoadBalanceStatus(ConnectionDTO.LOAD_BALANCE_INACTIVE);
        }

        return dto;
    }

    /**
     * Creates a ConnectableDTO from the specified Connectable.
     *
     * @param connectable connectable
     * @return dto
     */
    public ConnectableDTO createConnectableDto(final Connectable connectable) {
        if (connectable == null) {
            return null;
        }

        boolean isAuthorized = connectable.isAuthorized(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());

        final ConnectableDTO dto = new ConnectableDTO();
        dto.setId(connectable.getIdentifier());
        dto.setName(isAuthorized ? connectable.getName() : connectable.getIdentifier());
        dto.setType(connectable.getConnectableType().name());
        dto.setVersionedComponentId(connectable.getVersionedComponentId().orElse(null));

        if (connectable instanceof RemoteGroupPort) {
            final RemoteGroupPort remoteGroupPort = (RemoteGroupPort) connectable;
            final RemoteProcessGroup remoteGroup = remoteGroupPort.getRemoteProcessGroup();
            dto.setGroupId(remoteGroup.getIdentifier());
            dto.setRunning(remoteGroupPort.isTargetRunning());
            dto.setTransmitting(remoteGroupPort.isRunning());
            dto.setExists(remoteGroupPort.getTargetExists());
            if (isAuthorized) {
                dto.setComments(remoteGroup.getComments());
            }
        } else {
            dto.setGroupId(connectable.getProcessGroup().getIdentifier());
            dto.setRunning(connectable.isRunning());
            if (isAuthorized) {
                dto.setComments(connectable.getComments());
            }
        }

        return dto;
    }

    /**
     * Creates a LabelDTO from the specified Label.
     *
     * @param label label
     * @return dto
     */
    public LabelDTO createLabelDto(final Label label) {
        if (label == null) {
            return null;
        }

        final LabelDTO dto = new LabelDTO();
        dto.setId(label.getIdentifier());
        dto.setPosition(createPositionDto(label.getPosition()));
        dto.setStyle(label.getStyle());
        dto.setHeight(label.getSize().getHeight());
        dto.setWidth(label.getSize().getWidth());
        dto.setLabel(label.getValue());
        dto.setParentGroupId(label.getProcessGroup().getIdentifier());
        dto.setVersionedComponentId(label.getVersionedComponentId().orElse(null));

        return dto;
    }

    /**
     * Creates a {@link UserDTO} from the specified {@link User}.
     *
     * @param user user
     * @return dto
     */
    public UserDTO createUserDto(final User user, final Set<TenantEntity> groups, final Set<AccessPolicySummaryEntity> accessPolicies) {
        if (user == null) {
            return null;
        }

        final UserDTO dto = new UserDTO();
        dto.setId(user.getIdentifier());
        dto.setUserGroups(groups);
        dto.setIdentity(user.getIdentity());
        dto.setConfigurable(AuthorizerCapabilityDetection.isUserConfigurable(authorizer, user));
        dto.setAccessPolicies(accessPolicies);

        return dto;
    }

    /**
     * Creates a {@link TenantDTO} from the specified {@link User}.
     *
     * @param user user
     * @return dto
     */
    public TenantDTO createTenantDTO(User user) {
        if (user == null) {
            return null;
        }

        final TenantDTO dto = new TenantDTO();
        dto.setId(user.getIdentifier());
        dto.setIdentity(user.getIdentity());
        dto.setConfigurable(AuthorizerCapabilityDetection.isUserConfigurable(authorizer, user));

        return dto;
    }

    /**
     * Creates a {@link UserGroupDTO} from the specified {@link Group}.
     *
     * @param userGroup user group
     * @return dto
     */
    public UserGroupDTO createUserGroupDto(final Group userGroup, Set<TenantEntity> users, final Set<AccessPolicySummaryEntity> accessPolicies) {
        if (userGroup == null) {
            return null;
        }

        // convert to access policies to handle backward compatibility due to incorrect
        // type in the UserGroupDTO
        final Set<AccessPolicyEntity> policies = accessPolicies.stream().map(summaryEntity -> {
            final AccessPolicyDTO policy = new AccessPolicyDTO();
            policy.setId(summaryEntity.getId());

            if (summaryEntity.getPermissions().getCanRead()) {
                final AccessPolicySummaryDTO summary = summaryEntity.getComponent();
                policy.setResource(summary.getResource());
                policy.setAction(summary.getAction());
                policy.setConfigurable(summary.getConfigurable());
                policy.setComponentReference(summary.getComponentReference());
            }

            return entityFactory.createAccessPolicyEntity(policy, summaryEntity.getRevision(), summaryEntity.getPermissions());
        }).collect(Collectors.toSet());

        final UserGroupDTO dto = new UserGroupDTO();
        dto.setId(userGroup.getIdentifier());
        dto.setUsers(users);
        dto.setIdentity(userGroup.getName());
        dto.setConfigurable(AuthorizerCapabilityDetection.isGroupConfigurable(authorizer, userGroup));
        dto.setAccessPolicies(policies);

        return dto;
    }

    /**
     * Creates a {@link TenantDTO} from the specified {@link User}.
     *
     * @param userGroup user
     * @return dto
     */
    public TenantDTO createTenantDTO(Group userGroup) {
        if (userGroup == null) {
            return null;
        }

        final TenantDTO dto = new TenantDTO();
        dto.setId(userGroup.getIdentifier());
        dto.setIdentity(userGroup.getName());
        dto.setConfigurable(AuthorizerCapabilityDetection.isGroupConfigurable(authorizer, userGroup));

        return dto;
    }

    /**
     * Creates a FunnelDTO from the specified Funnel.
     *
     * @param funnel funnel
     * @return dto
     */
    public FunnelDTO createFunnelDto(final Funnel funnel) {
        if (funnel == null) {
            return null;
        }

        final FunnelDTO dto = new FunnelDTO();
        dto.setId(funnel.getIdentifier());
        dto.setPosition(createPositionDto(funnel.getPosition()));
        dto.setParentGroupId(funnel.getProcessGroup().getIdentifier());
        dto.setVersionedComponentId(funnel.getVersionedComponentId().orElse(null));

        return dto;
    }

    /**
     * Creates a SnippetDTO from the specified Snippet.
     *
     * @param snippet snippet
     * @return dto
     */
    public SnippetDTO createSnippetDto(final Snippet snippet) {
        final SnippetDTO dto = new SnippetDTO();
        dto.setId(snippet.getId());
        dto.setParentGroupId(snippet.getParentGroupId());

        // populate the snippet contents ids
        dto.setConnections(mapRevisionToDto(snippet.getConnections()));
        dto.setFunnels(mapRevisionToDto(snippet.getFunnels()));
        dto.setInputPorts(mapRevisionToDto(snippet.getInputPorts()));
        dto.setLabels(mapRevisionToDto(snippet.getLabels()));
        dto.setOutputPorts(mapRevisionToDto(snippet.getOutputPorts()));
        dto.setProcessGroups(mapRevisionToDto(snippet.getProcessGroups()));
        dto.setProcessors(mapRevisionToDto(snippet.getProcessors()));
        dto.setRemoteProcessGroups(mapRevisionToDto(snippet.getRemoteProcessGroups()));

        return dto;
    }

    private Map<String, RevisionDTO> mapRevisionToDto(final Map<String, Revision> revisionMap) {
        final Map<String, RevisionDTO> dtos = new HashMap<>(revisionMap.size());
        for (final Map.Entry<String, Revision> entry : revisionMap.entrySet()) {
            final Revision revision = entry.getValue();
            final RevisionDTO revisionDto = new RevisionDTO();
            revisionDto.setClientId(revision.getClientId());
            revisionDto.setVersion(revision.getVersion());

            dtos.put(entry.getKey(), revisionDto);
        }
        return dtos;
    }

    /**
     * Creates a TemplateDTO from the specified template.
     *
     * @param template template
     * @return dto
     */
    public TemplateDTO createTemplateDTO(final Template template) {
        if (template == null) {
            return null;
        }

        final TemplateDTO original = template.getDetails();

        final TemplateDTO copy = new TemplateDTO();
        copy.setId(original.getId());
        copy.setGroupId(template.getProcessGroup().getIdentifier());
        copy.setName(original.getName());
        copy.setDescription(original.getDescription());
        copy.setTimestamp(original.getTimestamp());
        copy.setUri(original.getUri());
        copy.setEncodingVersion(original.getEncodingVersion());

        return copy;
    }


    public RemoteProcessGroupStatusDTO createRemoteProcessGroupStatusDto(final RemoteProcessGroup remoteProcessGroup, final RemoteProcessGroupStatus remoteProcessGroupStatus) {
        final RemoteProcessGroupStatusDTO dto = new RemoteProcessGroupStatusDTO();
        dto.setId(remoteProcessGroupStatus.getId());
        dto.setGroupId(remoteProcessGroupStatus.getGroupId());
        dto.setTargetUri(remoteProcessGroupStatus.getTargetUri());
        dto.setName(remoteProcessGroupStatus.getName());
        dto.setTransmissionStatus(remoteProcessGroupStatus.getTransmissionStatus().toString());
        dto.setStatsLastRefreshed(new Date());
        dto.setValidationStatus(getRemoteProcessGroupValidationStatus(remoteProcessGroup).name());

        final RemoteProcessGroupStatusSnapshotDTO snapshot = new RemoteProcessGroupStatusSnapshotDTO();
        dto.setAggregateSnapshot(snapshot);

        snapshot.setId(remoteProcessGroupStatus.getId());
        snapshot.setGroupId(remoteProcessGroupStatus.getGroupId());
        snapshot.setName(remoteProcessGroupStatus.getName());
        snapshot.setTargetUri(remoteProcessGroupStatus.getTargetUri());
        snapshot.setTransmissionStatus(remoteProcessGroupStatus.getTransmissionStatus().toString());

        snapshot.setActiveThreadCount(remoteProcessGroupStatus.getActiveThreadCount());
        snapshot.setFlowFilesSent(remoteProcessGroupStatus.getSentCount());
        snapshot.setBytesSent(remoteProcessGroupStatus.getSentContentSize());
        snapshot.setFlowFilesReceived(remoteProcessGroupStatus.getReceivedCount());
        snapshot.setBytesReceived(remoteProcessGroupStatus.getReceivedContentSize());

        StatusMerger.updatePrettyPrintedFields(snapshot);
        return dto;
    }

    private ValidationStatus getRemoteProcessGroupValidationStatus(RemoteProcessGroup remoteProcessGroup) {
        final boolean hasAuthIssue = remoteProcessGroup.getAuthorizationIssue() != null && !remoteProcessGroup.getAuthorizationIssue().isEmpty();
        final Collection<ValidationResult> validationResults = remoteProcessGroup.validate();
        final boolean hasValidationIssue = validationResults != null && !validationResults.isEmpty();
        return hasAuthIssue || hasValidationIssue ? ValidationStatus.INVALID : ValidationStatus.VALID;
    }

    public ProcessGroupStatusDTO createConciseProcessGroupStatusDto(final ProcessGroupStatus processGroupStatus) {
        final ProcessGroupStatusDTO processGroupStatusDto = new ProcessGroupStatusDTO();
        processGroupStatusDto.setId(processGroupStatus.getId());
        processGroupStatusDto.setName(processGroupStatus.getName());
        processGroupStatusDto.setStatsLastRefreshed(new Date());

        final ProcessGroupStatusSnapshotDTO snapshot = new ProcessGroupStatusSnapshotDTO();
        processGroupStatusDto.setAggregateSnapshot(snapshot);

        snapshot.setId(processGroupStatus.getId());
        snapshot.setName(processGroupStatus.getName());

        if (processGroupStatus.getVersionedFlowState() != null) {
            snapshot.setVersionedFlowState(processGroupStatus.getVersionedFlowState().name());
        }

        snapshot.setFlowFilesQueued(processGroupStatus.getQueuedCount());
        snapshot.setBytesQueued(processGroupStatus.getQueuedContentSize());
        snapshot.setBytesRead(processGroupStatus.getBytesRead());
        snapshot.setBytesWritten(processGroupStatus.getBytesWritten());
        snapshot.setFlowFilesIn(processGroupStatus.getInputCount());
        snapshot.setBytesIn(processGroupStatus.getInputContentSize());
        snapshot.setFlowFilesOut(processGroupStatus.getOutputCount());
        snapshot.setBytesOut(processGroupStatus.getOutputContentSize());
        snapshot.setFlowFilesTransferred(processGroupStatus.getFlowFilesTransferred());
        snapshot.setBytesTransferred(processGroupStatus.getBytesTransferred());
        snapshot.setFlowFilesSent(processGroupStatus.getFlowFilesSent());
        snapshot.setBytesSent(processGroupStatus.getBytesSent());
        snapshot.setFlowFilesReceived(processGroupStatus.getFlowFilesReceived());
        snapshot.setBytesReceived(processGroupStatus.getBytesReceived());

        snapshot.setActiveThreadCount(processGroupStatus.getActiveThreadCount());
        snapshot.setTerminatedThreadCount(processGroupStatus.getTerminatedThreadCount());

        StatusMerger.updatePrettyPrintedFields(snapshot);
        return processGroupStatusDto;
    }

    public ProcessGroupStatusDTO createProcessGroupStatusDto(final ProcessGroup processGroup, final ProcessGroupStatus processGroupStatus) {
        final ProcessGroupStatusDTO processGroupStatusDto = createConciseProcessGroupStatusDto(processGroupStatus);
        final ProcessGroupStatusSnapshotDTO snapshot = processGroupStatusDto.getAggregateSnapshot();

        // processor status
        final Collection<ProcessorStatusSnapshotEntity> processorStatusSnapshotEntities = new ArrayList<>();
        snapshot.setProcessorStatusSnapshots(processorStatusSnapshotEntities);
        final Collection<ProcessorStatus> processorStatusCollection = processGroupStatus.getProcessorStatus();
        if (processorStatusCollection != null) {
            for (final ProcessorStatus processorStatus : processorStatusCollection) {
                final ProcessorStatusDTO processorStatusDto = createProcessorStatusDto(processorStatus);
                final ProcessorNode processor = processGroup.findProcessor(processorStatusDto.getId());
                final PermissionsDTO processorPermissions = createPermissionsDto(processor);
                processorStatusSnapshotEntities.add(entityFactory.createProcessorStatusSnapshotEntity(processorStatusDto.getAggregateSnapshot(), processorPermissions));
            }
        }

        // connection status
        final Collection<ConnectionStatusSnapshotEntity> connectionStatusDtoCollection = new ArrayList<>();
        snapshot.setConnectionStatusSnapshots(connectionStatusDtoCollection);
        final Collection<ConnectionStatus> connectionStatusCollection = processGroupStatus.getConnectionStatus();
        if (connectionStatusCollection != null) {
            for (final ConnectionStatus connectionStatus : connectionStatusCollection) {
                final ConnectionStatusDTO connectionStatusDto = createConnectionStatusDto(connectionStatus);
                final Connection connection = processGroup.findConnection(connectionStatusDto.getId());
                final PermissionsDTO connectionPermissions = createPermissionsDto(connection);
                connectionStatusDtoCollection.add(entityFactory.createConnectionStatusSnapshotEntity(connectionStatusDto.getAggregateSnapshot(), connectionPermissions));
            }
        }

        // local child process groups
        final Collection<ProcessGroupStatusSnapshotEntity> childProcessGroupStatusDtoCollection = new ArrayList<>();
        snapshot.setProcessGroupStatusSnapshots(childProcessGroupStatusDtoCollection);
        final Collection<ProcessGroupStatus> childProcessGroupStatusCollection = processGroupStatus.getProcessGroupStatus();
        if (childProcessGroupStatusCollection != null) {
            for (final ProcessGroupStatus childProcessGroupStatus : childProcessGroupStatusCollection) {
                final ProcessGroupStatusDTO childProcessGroupStatusDto = createProcessGroupStatusDto(processGroup, childProcessGroupStatus);
                final ProcessGroup childProcessGroup = processGroup.findProcessGroup(childProcessGroupStatusDto.getId());
                final PermissionsDTO childProcessGroupPermissions = createPermissionsDto(childProcessGroup);
                childProcessGroupStatusDtoCollection.add(entityFactory.createProcessGroupStatusSnapshotEntity(childProcessGroupStatusDto.getAggregateSnapshot(), childProcessGroupPermissions));
            }
        }

        // remote child process groups
        final Collection<RemoteProcessGroupStatusSnapshotEntity> childRemoteProcessGroupStatusDtoCollection = new ArrayList<>();
        snapshot.setRemoteProcessGroupStatusSnapshots(childRemoteProcessGroupStatusDtoCollection);
        final Collection<RemoteProcessGroupStatus> childRemoteProcessGroupStatusCollection = processGroupStatus.getRemoteProcessGroupStatus();
        if (childRemoteProcessGroupStatusCollection != null) {
            for (final RemoteProcessGroupStatus childRemoteProcessGroupStatus : childRemoteProcessGroupStatusCollection) {
                final RemoteProcessGroup remoteProcessGroup = processGroup.findRemoteProcessGroup(childRemoteProcessGroupStatus.getId());
                final RemoteProcessGroupStatusDTO childRemoteProcessGroupStatusDto = createRemoteProcessGroupStatusDto(remoteProcessGroup, childRemoteProcessGroupStatus);
                final PermissionsDTO remoteProcessGroupPermissions = createPermissionsDto(remoteProcessGroup);
                childRemoteProcessGroupStatusDtoCollection.add(entityFactory.createRemoteProcessGroupStatusSnapshotEntity(childRemoteProcessGroupStatusDto.getAggregateSnapshot(),
                        remoteProcessGroupPermissions));
            }
        }

        // input ports
        final Collection<PortStatusSnapshotEntity> inputPortStatusDtoCollection = new ArrayList<>();
        snapshot.setInputPortStatusSnapshots(inputPortStatusDtoCollection);
        final Collection<PortStatus> inputPortStatusCollection = processGroupStatus.getInputPortStatus();
        if (inputPortStatusCollection != null) {
            for (final PortStatus portStatus : inputPortStatusCollection) {
                final PortStatusDTO portStatusDto = createPortStatusDto(portStatus);
                final Port inputPort = processGroup.findInputPort(portStatus.getId());
                final PermissionsDTO inputPortPermissions = createPermissionsDto(inputPort);
                inputPortStatusDtoCollection.add(entityFactory.createPortStatusSnapshotEntity(portStatusDto.getAggregateSnapshot(), inputPortPermissions));
            }
        }

        // output ports
        final Collection<PortStatusSnapshotEntity> outputPortStatusDtoCollection = new ArrayList<>();
        snapshot.setOutputPortStatusSnapshots(outputPortStatusDtoCollection);
        final Collection<PortStatus> outputPortStatusCollection = processGroupStatus.getOutputPortStatus();
        if (outputPortStatusCollection != null) {
            for (final PortStatus portStatus : outputPortStatusCollection) {
                final PortStatusDTO portStatusDto = createPortStatusDto(portStatus);
                final Port outputPort = processGroup.findOutputPort(portStatus.getId());
                final PermissionsDTO outputPortPermissions = createPermissionsDto(outputPort);
                outputPortStatusDtoCollection.add(entityFactory.createPortStatusSnapshotEntity(portStatusDto.getAggregateSnapshot(), outputPortPermissions));
            }
        }

        return processGroupStatusDto;
    }

    public ConnectionStatusDTO createConnectionStatusDto(final ConnectionStatus connectionStatus) {
        final ConnectionStatusDTO connectionStatusDto = new ConnectionStatusDTO();
        connectionStatusDto.setGroupId(connectionStatus.getGroupId());
        connectionStatusDto.setId(connectionStatus.getId());
        connectionStatusDto.setName(connectionStatus.getName());
        connectionStatusDto.setSourceId(connectionStatus.getSourceId());
        connectionStatusDto.setSourceName(connectionStatus.getSourceName());
        connectionStatusDto.setDestinationId(connectionStatus.getDestinationId());
        connectionStatusDto.setDestinationName(connectionStatus.getDestinationName());
        connectionStatusDto.setStatsLastRefreshed(new Date());

        final ConnectionStatusSnapshotDTO snapshot = new ConnectionStatusSnapshotDTO();
        connectionStatusDto.setAggregateSnapshot(snapshot);

        snapshot.setId(connectionStatus.getId());
        snapshot.setGroupId(connectionStatus.getGroupId());
        snapshot.setName(connectionStatus.getName());
        snapshot.setSourceName(connectionStatus.getSourceName());
        snapshot.setDestinationName(connectionStatus.getDestinationName());

        snapshot.setFlowFilesQueued(connectionStatus.getQueuedCount());
        snapshot.setBytesQueued(connectionStatus.getQueuedBytes());

        snapshot.setFlowFilesIn(connectionStatus.getInputCount());
        snapshot.setBytesIn(connectionStatus.getInputBytes());

        snapshot.setFlowFilesOut(connectionStatus.getOutputCount());
        snapshot.setBytesOut(connectionStatus.getOutputBytes());

        ConnectionStatusPredictions predictions = connectionStatus.getPredictions();
        ConnectionStatusPredictionsSnapshotDTO predictionsDTO = null;
        if (predictions != null) {
            predictionsDTO = new ConnectionStatusPredictionsSnapshotDTO();
        }

        if (connectionStatus.getBackPressureObjectThreshold() > 0) {
            snapshot.setPercentUseCount(Math.min(100, StatusMerger.getUtilization(connectionStatus.getQueuedCount(), connectionStatus.getBackPressureObjectThreshold())));

            if (predictionsDTO != null) {
                snapshot.setPredictions(predictionsDTO);
                predictionsDTO.setPredictionIntervalSeconds(((Long) (predictions.getPredictionIntervalMillis() / 1000L)).intValue());
                predictionsDTO.setPredictedMillisUntilCountBackpressure(predictions.getPredictedTimeToCountBackpressureMillis());
                predictionsDTO.setPredictedCountAtNextInterval(predictions.getNextPredictedQueuedCount());
                predictionsDTO.setPredictedPercentCount(predictions.getPredictedPercentCount());
                predictionsDTO.setPredictedPercentBytes(predictions.getPredictedPercentBytes());
                predictionsDTO.setPredictionIntervalSeconds(((Long) (predictions.getPredictionIntervalMillis() / 1000L)).intValue());
            }
        }
        if (connectionStatus.getBackPressureBytesThreshold() > 0) {
            snapshot.setPercentUseBytes(Math.min(100, StatusMerger.getUtilization(connectionStatus.getQueuedBytes(), connectionStatus.getBackPressureBytesThreshold())));

            if (predictionsDTO != null) {
                snapshot.setPredictions(predictionsDTO);
                predictionsDTO.setPredictionIntervalSeconds(((Long) (predictions.getPredictionIntervalMillis() / 1000L)).intValue());
                predictionsDTO.setPredictedMillisUntilBytesBackpressure(predictions.getPredictedTimeToBytesBackpressureMillis());
                predictionsDTO.setPredictedBytesAtNextInterval(predictions.getNextPredictedQueuedBytes());
                predictionsDTO.setPredictedPercentCount(predictions.getPredictedPercentCount());
                predictionsDTO.setPredictedPercentBytes(predictions.getPredictedPercentBytes());
                predictionsDTO.setPredictionIntervalSeconds(((Long) (predictions.getPredictionIntervalMillis() / 1000L)).intValue());
            }
        }

        StatusMerger.updatePrettyPrintedFields(snapshot);

        return connectionStatusDto;
    }

    public ConnectionStatisticsDTO createConnectionStatisticsDto(final Connection connection, final StatusAnalytics statusAnalytics) {
        final ConnectionStatisticsDTO connectionStatisticsDTO = new ConnectionStatisticsDTO();

        connectionStatisticsDTO.setId(connection.getIdentifier());
        connectionStatisticsDTO.setStatsLastRefreshed(new Date());

        final ConnectionStatisticsSnapshotDTO snapshot = new ConnectionStatisticsSnapshotDTO();
        connectionStatisticsDTO.setAggregateSnapshot(snapshot);

        snapshot.setId(connection.getIdentifier());

        Map<String,Long> predictions = statusAnalytics.getPredictions();
        snapshot.setPredictedMillisUntilBytesBackpressure(predictions.get("timeToBytesBackpressureMillis"));
        snapshot.setPredictedMillisUntilCountBackpressure(predictions.get("timeToCountBackpressureMillis"));
        snapshot.setPredictedBytesAtNextInterval(predictions.get("nextIntervalBytes"));
        snapshot.setPredictedCountAtNextInterval(predictions.get("nextIntervalCount").intValue());
        snapshot.setPredictedPercentBytes(predictions.get("nextIntervalPercentageUseBytes").intValue());
        snapshot.setPredictedPercentCount(predictions.get("nextIntervalPercentageUseCount").intValue());
        snapshot.setPredictionIntervalMillis(predictions.get("intervalTimeMillis"));

        return connectionStatisticsDTO;
    }

    public ProcessorStatusDTO createProcessorStatusDto(final ProcessorStatus procStatus) {
        final ProcessorStatusDTO dto = new ProcessorStatusDTO();
        dto.setId(procStatus.getId());
        dto.setGroupId(procStatus.getGroupId());
        dto.setName(procStatus.getName());
        dto.setStatsLastRefreshed(new Date());
        dto.setRunStatus(procStatus.getRunStatus().toString());

        final ProcessorStatusSnapshotDTO snapshot = new ProcessorStatusSnapshotDTO();
        dto.setAggregateSnapshot(snapshot);

        snapshot.setId(procStatus.getId());
        snapshot.setGroupId(procStatus.getGroupId());
        snapshot.setName(procStatus.getName());

        snapshot.setFlowFilesOut(procStatus.getOutputCount());
        snapshot.setBytesOut(procStatus.getOutputBytes());

        snapshot.setFlowFilesIn(procStatus.getInputCount());
        snapshot.setBytesIn(procStatus.getInputBytes());

        snapshot.setBytesRead(procStatus.getBytesRead());
        snapshot.setBytesWritten(procStatus.getBytesWritten());

        snapshot.setTaskCount(procStatus.getInvocations());
        snapshot.setTasksDurationNanos(procStatus.getProcessingNanos());
        snapshot.setTasksDuration(FormatUtils.formatHoursMinutesSeconds(procStatus.getProcessingNanos(), TimeUnit.NANOSECONDS));

        // determine the run status
        snapshot.setRunStatus(procStatus.getRunStatus().toString());
        snapshot.setExecutionNode(procStatus.getExecutionNode().toString());

        snapshot.setActiveThreadCount(procStatus.getActiveThreadCount());
        snapshot.setTerminatedThreadCount(procStatus.getTerminatedThreadCount());
        snapshot.setType(procStatus.getType());

        StatusMerger.updatePrettyPrintedFields(snapshot);
        return dto;
    }

    public ProcessorRunStatusDetailsDTO createProcessorRunStatusDetailsDto(final ProcessorNode processor, final ProcessorStatus processorStatus) {
        final ProcessorRunStatusDetailsDTO dto = new ProcessorRunStatusDetailsDTO();
        dto.setId(processor.getIdentifier());
        dto.setName(processor.getName());
        dto.setActiveThreadCount(processorStatus.getActiveThreadCount());
        dto.setRunStatus(processorStatus.getRunStatus().name());
        dto.setValidationErrors(convertValidationErrors(processor.getValidationErrors()));
        return dto;
    }

    private Set<String> convertValidationErrors(final Collection<ValidationResult> validationErrors) {
        if (validationErrors == null) {
            return null;
        }
        if (validationErrors.isEmpty()) {
            return Collections.emptySet();
        }

        final Set<String> errors = new HashSet<>(validationErrors.size());
        for (final ValidationResult result : validationErrors) {
            errors.add(result.toString());
        }

        return errors;
    }

    /**
     * Creates a PortStatusDTO for the specified PortStatus.
     *
     * @param portStatus status
     * @return dto
     */
    public PortStatusDTO createPortStatusDto(final PortStatus portStatus) {
        final PortStatusDTO dto = new PortStatusDTO();
        dto.setId(portStatus.getId());
        dto.setGroupId(portStatus.getGroupId());
        dto.setName(portStatus.getName());
        dto.setRunStatus(portStatus.getRunStatus().toString());
        dto.setTransmitting(portStatus.isTransmitting());
        dto.setStatsLastRefreshed(new Date());

        final PortStatusSnapshotDTO snapshot = new PortStatusSnapshotDTO();
        dto.setAggregateSnapshot(snapshot);

        snapshot.setId(portStatus.getId());
        snapshot.setGroupId(portStatus.getGroupId());
        snapshot.setName(portStatus.getName());
        snapshot.setRunStatus(portStatus.getRunStatus().toString());

        snapshot.setActiveThreadCount(portStatus.getActiveThreadCount());
        snapshot.setFlowFilesOut(portStatus.getOutputCount());
        snapshot.setBytesOut(portStatus.getOutputBytes());

        snapshot.setFlowFilesIn(portStatus.getInputCount());
        snapshot.setBytesIn(portStatus.getInputBytes());
        StatusMerger.updatePrettyPrintedFields(snapshot);

        return dto;
    }

    /**
     * Copies the specified snippet.
     *
     * @param originalSnippet snippet
     * @return dto
     */
    public FlowSnippetDTO copySnippetContents(final FlowSnippetDTO originalSnippet) {
        final FlowSnippetDTO copySnippet = new FlowSnippetDTO();

        if (originalSnippet.getConnections() != null) {
            for (final ConnectionDTO connection : originalSnippet.getConnections()) {
                copySnippet.getConnections().add(copy(connection));
            }
        }
        if (originalSnippet.getInputPorts() != null) {
            for (final PortDTO port : originalSnippet.getInputPorts()) {
                copySnippet.getInputPorts().add(copy(port));
            }
        }
        if (originalSnippet.getOutputPorts() != null) {
            for (final PortDTO port : originalSnippet.getOutputPorts()) {
                copySnippet.getOutputPorts().add(copy(port));
            }
        }
        if (originalSnippet.getProcessGroups() != null) {
            for (final ProcessGroupDTO processGroup : originalSnippet.getProcessGroups()) {
                copySnippet.getProcessGroups().add(copy(processGroup, true));
            }
        }
        if (originalSnippet.getProcessors() != null) {
            for (final ProcessorDTO processor : originalSnippet.getProcessors()) {
                copySnippet.getProcessors().add(copy(processor));
            }
        }
        if (originalSnippet.getLabels() != null) {
            for (final LabelDTO label : originalSnippet.getLabels()) {
                copySnippet.getLabels().add(copy(label));
            }
        }
        if (originalSnippet.getFunnels() != null) {
            for (final FunnelDTO funnel : originalSnippet.getFunnels()) {
                copySnippet.getFunnels().add(copy(funnel));
            }
        }
        if (originalSnippet.getRemoteProcessGroups() != null) {
            for (final RemoteProcessGroupDTO remoteGroup : originalSnippet.getRemoteProcessGroups()) {
                copySnippet.getRemoteProcessGroups().add(copy(remoteGroup));
            }
        }
        if (originalSnippet.getControllerServices() != null) {
            for (final ControllerServiceDTO controllerService : originalSnippet.getControllerServices()) {
                copySnippet.getControllerServices().add(copy(controllerService));
            }
        }

        return copySnippet;
    }

    /**
     * Creates a PortDTO from the specified Port.
     *
     * @param port port
     * @return dto
     */
    public PortDTO createPortDto(final Port port) {
        if (port == null) {
            return null;
        }

        final PortDTO dto = new PortDTO();
        dto.setId(port.getIdentifier());
        dto.setPosition(createPositionDto(port.getPosition()));
        dto.setName(port.getName());
        dto.setComments(port.getComments());
        dto.setConcurrentlySchedulableTaskCount(port.getMaxConcurrentTasks());
        dto.setParentGroupId(port.getProcessGroup().getIdentifier());
        dto.setState(port.getScheduledState().toString());
        dto.setType(port.getConnectableType().name());
        dto.setVersionedComponentId(port.getVersionedComponentId().orElse(null));

        // if this port is remotely accessible, determine if its actually connected to another nifi
        if (port instanceof PublicPort) {
            final PublicPort publicPort = (PublicPort) port;
            dto.setAllowRemoteAccess(true);
            dto.setTransmitting(publicPort.isTransmitting());
            dto.setGroupAccessControl(publicPort.getGroupAccessControl());
            dto.setUserAccessControl(publicPort.getUserAccessControl());
        }

        final Collection<ValidationResult> validationErrors = port.getValidationErrors();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        return dto;
    }

    public ParameterContextDTO createParameterContextDto(final ParameterContext parameterContext, final RevisionManager revisionManager) {
        final ParameterContextDTO dto = new ParameterContextDTO();
        dto.setId(parameterContext.getIdentifier());
        dto.setName(parameterContext.getName());
        dto.setDescription(parameterContext.getDescription());

        final Set<ProcessGroupEntity> boundGroups = new HashSet<>();
        for (final ProcessGroup processGroup : parameterContext.getParameterReferenceManager().getProcessGroupsBound(parameterContext)) {
            final ProcessGroupDTO processGroupDto = createConciseProcessGroupDto(processGroup);
            final RevisionDTO revisionDto = createRevisionDTO(revisionManager.getRevision(processGroup.getIdentifier()));
            final PermissionsDTO permissionsDto = createPermissionsDto(processGroup);
            final ProcessGroupEntity processGroupEntity = entityFactory.createProcessGroupEntity(processGroupDto, revisionDto, permissionsDto, null, null);
            boundGroups.add(processGroupEntity);
        }
        dto.setBoundProcessGroups(boundGroups);

        final Set<ParameterEntity> parameterEntities = new LinkedHashSet<>();
        for (final Parameter parameter : parameterContext.getParameters().values()) {
            parameterEntities.add(createParameterEntity(parameterContext, parameter, revisionManager));
        }

        dto.setParameters(parameterEntities);
        return dto;
    }

    public ParameterEntity createParameterEntity(final ParameterContext parameterContext, final Parameter parameter, final RevisionManager revisionManager) {
        final ParameterDTO dto = createParameterDto(parameterContext, parameter, revisionManager);
        final ParameterEntity entity = new ParameterEntity();
        entity.setParameter(dto);

        final boolean canWrite = isWritable(dto.getReferencingComponents());
        entity.setCanWrite(canWrite);

        return entity;
    }

    public ParameterDTO createParameterDto(final ParameterContext parameterContext, final Parameter parameter, final RevisionManager revisionManager) {
        final ParameterDescriptor descriptor = parameter.getDescriptor();

        final ParameterDTO dto = new ParameterDTO();
        dto.setName(descriptor.getName());
        dto.setDescription(descriptor.getDescription());
        dto.setSensitive(descriptor.isSensitive());
        if (parameter.getValue() != null) {
            dto.setValue(descriptor.isSensitive() ? SENSITIVE_VALUE_MASK : parameter.getValue());
        }

        final ParameterReferenceManager parameterReferenceManager = parameterContext.getParameterReferenceManager();

        final Set<ComponentNode> referencingComponents = new HashSet<>();
        referencingComponents.addAll(parameterReferenceManager.getProcessorsReferencing(parameterContext, descriptor.getName()));
        referencingComponents.addAll(parameterReferenceManager.getControllerServicesReferencing(parameterContext, descriptor.getName()));

        final Set<AffectedComponentEntity> referencingComponentEntities = createAffectedComponentEntities(referencingComponents, revisionManager);
        dto.setReferencingComponents(referencingComponentEntities);

        return dto;
    }

    public ReportingTaskDTO createReportingTaskDto(final ReportingTaskNode reportingTaskNode) {
        final BundleCoordinate bundleCoordinate = reportingTaskNode.getBundleCoordinate();
        final List<Bundle> compatibleBundles = extensionManager.getBundles(reportingTaskNode.getCanonicalClassName()).stream().filter(bundle -> {
            final BundleCoordinate coordinate = bundle.getBundleDetails().getCoordinate();
            return bundleCoordinate.getGroup().equals(coordinate.getGroup()) && bundleCoordinate.getId().equals(coordinate.getId());
        }).collect(Collectors.toList());

        final ReportingTaskDTO dto = new ReportingTaskDTO();
        dto.setId(reportingTaskNode.getIdentifier());
        dto.setName(reportingTaskNode.getName());
        dto.setType(reportingTaskNode.getCanonicalClassName());
        dto.setBundle(createBundleDto(bundleCoordinate));
        dto.setSchedulingStrategy(reportingTaskNode.getSchedulingStrategy().name());
        dto.setSchedulingPeriod(reportingTaskNode.getSchedulingPeriod());
        dto.setState(reportingTaskNode.getScheduledState().name());
        dto.setActiveThreadCount(reportingTaskNode.getActiveThreadCount());
        dto.setAnnotationData(reportingTaskNode.getAnnotationData());
        dto.setComments(reportingTaskNode.getComments());
        dto.setPersistsState(reportingTaskNode.getReportingTask().getClass().isAnnotationPresent(Stateful.class));
        dto.setRestricted(reportingTaskNode.isRestricted());
        dto.setDeprecated(reportingTaskNode.isDeprecated());
        dto.setExtensionMissing(reportingTaskNode.isExtensionMissing());
        dto.setMultipleVersionsAvailable(compatibleBundles.size() > 1);

        final Map<String, String> defaultSchedulingPeriod = new HashMap<>();
        defaultSchedulingPeriod.put(SchedulingStrategy.TIMER_DRIVEN.name(), SchedulingStrategy.TIMER_DRIVEN.getDefaultSchedulingPeriod());
        defaultSchedulingPeriod.put(SchedulingStrategy.CRON_DRIVEN.name(), SchedulingStrategy.CRON_DRIVEN.getDefaultSchedulingPeriod());
        dto.setDefaultSchedulingPeriod(defaultSchedulingPeriod);

        // sort a copy of the properties
        final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
            @Override
            public int compare(final PropertyDescriptor o1, final PropertyDescriptor o2) {
                return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
            }
        });
        sortedProperties.putAll(reportingTaskNode.getRawPropertyValues());

        // get the property order from the reporting task
        final ReportingTask reportingTask = reportingTaskNode.getReportingTask();
        final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
        final List<PropertyDescriptor> descriptors = reportingTask.getPropertyDescriptors();
        if (descriptors != null && !descriptors.isEmpty()) {
            for (final PropertyDescriptor descriptor : descriptors) {
                orderedProperties.put(descriptor, null);
            }
        }
        orderedProperties.putAll(sortedProperties);

        // build the descriptor and property dtos
        dto.setDescriptors(new LinkedHashMap<>());
        dto.setProperties(new LinkedHashMap<>());
        for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
            final PropertyDescriptor descriptor = entry.getKey();

            // store the property descriptor
            dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor, null));

            // determine the property value - don't include sensitive properties
            String propertyValue = entry.getValue();
            if (propertyValue != null && descriptor.isSensitive()) {
                propertyValue = SENSITIVE_VALUE_MASK;
            } else if (propertyValue == null && descriptor.getDefaultValue() != null) {
                propertyValue = descriptor.getDefaultValue();
            }

            // set the property value
            dto.getProperties().put(descriptor.getName(), propertyValue);
        }

        final ValidationStatus validationStatus = reportingTaskNode.getValidationStatus(1, TimeUnit.MILLISECONDS);
        dto.setValidationStatus(validationStatus.name());

        // add the validation errors
        final Collection<ValidationResult> validationErrors = reportingTaskNode.getValidationErrors();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        return dto;
    }

    public ControllerServiceDTO createControllerServiceDto(final ControllerServiceNode controllerServiceNode) {
        final BundleCoordinate bundleCoordinate = controllerServiceNode.getBundleCoordinate();
        final List<Bundle> compatibleBundles = extensionManager.getBundles(controllerServiceNode.getCanonicalClassName()).stream().filter(bundle -> {
            final BundleCoordinate coordinate = bundle.getBundleDetails().getCoordinate();
            return bundleCoordinate.getGroup().equals(coordinate.getGroup()) && bundleCoordinate.getId().equals(coordinate.getId());
        }).collect(Collectors.toList());

        final ControllerServiceDTO dto = new ControllerServiceDTO();
        dto.setId(controllerServiceNode.getIdentifier());
        dto.setParentGroupId(controllerServiceNode.getProcessGroup() == null ? null : controllerServiceNode.getProcessGroup().getIdentifier());
        dto.setName(controllerServiceNode.getName());
        dto.setType(controllerServiceNode.getCanonicalClassName());
        dto.setBundle(createBundleDto(bundleCoordinate));
        dto.setControllerServiceApis(createControllerServiceApiDto(controllerServiceNode.getControllerServiceImplementation().getClass()));
        dto.setState(controllerServiceNode.getState().name());
        dto.setAnnotationData(controllerServiceNode.getAnnotationData());
        dto.setComments(controllerServiceNode.getComments());
        dto.setPersistsState(controllerServiceNode.getControllerServiceImplementation().getClass().isAnnotationPresent(Stateful.class));
        dto.setRestricted(controllerServiceNode.isRestricted());
        dto.setDeprecated(controllerServiceNode.isDeprecated());
        dto.setExtensionMissing(controllerServiceNode.isExtensionMissing());
        dto.setMultipleVersionsAvailable(compatibleBundles.size() > 1);
        dto.setVersionedComponentId(controllerServiceNode.getVersionedComponentId().orElse(null));

        // sort a copy of the properties
        final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
            @Override
            public int compare(final PropertyDescriptor o1, final PropertyDescriptor o2) {
                return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
            }
        });
        sortedProperties.putAll(controllerServiceNode.getRawPropertyValues());

        // get the property order from the controller service
        final ControllerService controllerService = controllerServiceNode.getControllerServiceImplementation();
        final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
        final List<PropertyDescriptor> descriptors = controllerService.getPropertyDescriptors();
        if (descriptors != null && !descriptors.isEmpty()) {
            for (final PropertyDescriptor descriptor : descriptors) {
                orderedProperties.put(descriptor, null);
            }
        }
        orderedProperties.putAll(sortedProperties);

        // build the descriptor and property dtos
        dto.setDescriptors(new LinkedHashMap<>());
        dto.setProperties(new LinkedHashMap<>());
        for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
            final PropertyDescriptor descriptor = entry.getKey();

            // store the property descriptor
            final String groupId = controllerServiceNode.getProcessGroup() == null ? null : controllerServiceNode.getProcessGroup().getIdentifier();
            dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor, groupId));

            // determine the property value - don't include sensitive properties
            String propertyValue = entry.getValue();
            if (propertyValue != null && descriptor.isSensitive()) {
                propertyValue = SENSITIVE_VALUE_MASK;
            } else if (propertyValue == null && descriptor.getDefaultValue() != null) {
                propertyValue = descriptor.getDefaultValue();
            }

            // set the property value
            dto.getProperties().put(descriptor.getName(), propertyValue);
        }

        dto.setValidationStatus(controllerServiceNode.getValidationStatus(1, TimeUnit.MILLISECONDS).name());

        // add the validation errors
        final Collection<ValidationResult> validationErrors = controllerServiceNode.getValidationErrors();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        return dto;
    }

    public ControllerServiceReferencingComponentDTO createControllerServiceReferencingComponentDTO(final ComponentNode component) {
        final ControllerServiceReferencingComponentDTO dto = new ControllerServiceReferencingComponentDTO();
        dto.setId(component.getIdentifier());
        dto.setName(component.getName());

        String processGroupId = null;
        List<PropertyDescriptor> propertyDescriptors = null;
        Collection<ValidationResult> validationErrors = null;
        if (component instanceof ProcessorNode) {
            final ProcessorNode node = ((ProcessorNode) component);
            dto.setGroupId(node.getProcessGroup().getIdentifier());
            dto.setState(node.getScheduledState().name());
            dto.setActiveThreadCount(node.getActiveThreadCount());
            dto.setType(node.getComponentType());
            dto.setReferenceType(Processor.class.getSimpleName());

            propertyDescriptors = node.getProcessor().getPropertyDescriptors();
            validationErrors = node.getValidationErrors();
            processGroupId = node.getProcessGroup().getIdentifier();
        } else if (component instanceof ControllerServiceNode) {
            final ControllerServiceNode node = ((ControllerServiceNode) component);
            dto.setState(node.getState().name());
            dto.setType(node.getComponentType());
            dto.setReferenceType(ControllerService.class.getSimpleName());

            propertyDescriptors = node.getControllerServiceImplementation().getPropertyDescriptors();
            validationErrors = node.getValidationErrors();
            processGroupId = node.getProcessGroup() == null ? null : node.getProcessGroup().getIdentifier();
        } else if (component instanceof ReportingTaskNode) {
            final ReportingTaskNode node = ((ReportingTaskNode) component);
            dto.setState(node.getScheduledState().name());
            dto.setActiveThreadCount(node.getActiveThreadCount());
            dto.setType(node.getComponentType());
            dto.setReferenceType(ReportingTask.class.getSimpleName());

            propertyDescriptors = node.getReportingTask().getPropertyDescriptors();
            validationErrors = node.getValidationErrors();
            processGroupId = null;
        }

        // ensure descriptors is non null
        if (propertyDescriptors == null) {
            propertyDescriptors = new ArrayList<>();
        }

        // process properties unconditionally since dynamic properties are available here and not in getPropertyDescriptors
        final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
            @Override
            public int compare(final PropertyDescriptor o1, final PropertyDescriptor o2) {
                return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
            }
        });
        sortedProperties.putAll(component.getRawPropertyValues());

        final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
        for (final PropertyDescriptor descriptor : propertyDescriptors) {
            orderedProperties.put(descriptor, null);
        }
        orderedProperties.putAll(sortedProperties);

        // build the descriptor and property dtos
        dto.setDescriptors(new LinkedHashMap<String, PropertyDescriptorDTO>());
        dto.setProperties(new LinkedHashMap<String, String>());
        for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
            final PropertyDescriptor descriptor = entry.getKey();

            // store the property descriptor
            dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor, processGroupId));

            // determine the property value - don't include sensitive properties
            String propertyValue = entry.getValue();
            if (propertyValue != null && descriptor.isSensitive()) {
                propertyValue = SENSITIVE_VALUE_MASK;
            }

            // set the property value
            dto.getProperties().put(descriptor.getName(), propertyValue);
        }

        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        return dto;
    }

    public RemoteProcessGroupPortDTO createRemoteProcessGroupPortDto(final RemoteGroupPort port) {
        if (port == null) {
            return null;
        }

        final RemoteProcessGroupPortDTO dto = new RemoteProcessGroupPortDTO();
        dto.setId(port.getIdentifier());
        dto.setGroupId(port.getRemoteProcessGroup().getIdentifier());
        dto.setTargetId(port.getTargetIdentifier());
        dto.setName(port.getName());
        dto.setComments(port.getComments());
        dto.setTransmitting(port.isRunning());
        dto.setTargetRunning(port.isTargetRunning());
        dto.setConcurrentlySchedulableTaskCount(port.getMaxConcurrentTasks());
        dto.setUseCompression(port.isUseCompression());
        dto.setExists(port.getTargetExists());
        dto.setVersionedComponentId(port.getVersionedComponentId().orElse(null));

        final BatchSettingsDTO batchDTO = new BatchSettingsDTO();
        batchDTO.setCount(port.getBatchCount());
        batchDTO.setSize(port.getBatchSize());
        batchDTO.setDuration(port.getBatchDuration());
        dto.setBatchSettings(batchDTO);

        // determine if this port is currently connected to another component locally
        if (ConnectableType.REMOTE_OUTPUT_PORT.equals(port.getConnectableType())) {
            dto.setConnected(!port.getConnections().isEmpty());
        } else {
            dto.setConnected(port.hasIncomingConnection());
        }

        return dto;
    }

    /**
     * Creates a RemoteProcessGroupDTO from the specified RemoteProcessGroup.
     *
     * @param group group
     * @return dto
     */
    public RemoteProcessGroupDTO createRemoteProcessGroupDto(final RemoteProcessGroup group) {
        if (group == null) {
            return null;
        }

        final Set<RemoteProcessGroupPortDTO> inputPorts = new HashSet<>();
        final Set<RemoteProcessGroupPortDTO> outputPorts = new HashSet<>();

        int activeRemoteInputPortCount = 0;
        int inactiveRemoteInputPortCount = 0;
        for (final Port port : group.getInputPorts()) {
            inputPorts.add(createRemoteProcessGroupPortDto((RemoteGroupPort) port));

            if (port.hasIncomingConnection()) {
                if (port.isRunning()) {
                    activeRemoteInputPortCount++;
                } else {
                    inactiveRemoteInputPortCount++;
                }
            }
        }

        int activeRemoteOutputPortCount = 0;
        int inactiveRemoteOutputPortCount = 0;
        for (final Port port : group.getOutputPorts()) {
            outputPorts.add(createRemoteProcessGroupPortDto((RemoteGroupPort) port));

            if (!port.getConnections().isEmpty()) {
                if (port.isRunning()) {
                    activeRemoteOutputPortCount++;
                } else {
                    inactiveRemoteOutputPortCount++;
                }
            }
        }

        final RemoteProcessGroupContentsDTO contents = new RemoteProcessGroupContentsDTO();
        contents.setInputPorts(inputPorts);
        contents.setOutputPorts(outputPorts);

        final RemoteProcessGroupDTO dto = new RemoteProcessGroupDTO();
        dto.setId(group.getIdentifier());
        dto.setName(group.getName());
        dto.setPosition(createPositionDto(group.getPosition()));
        dto.setComments(group.getComments());
        dto.setTransmitting(group.isTransmitting());
        dto.setCommunicationsTimeout(group.getCommunicationsTimeout());
        dto.setYieldDuration(group.getYieldDuration());
        dto.setParentGroupId(group.getProcessGroup().getIdentifier());
        dto.setTargetUris(group.getTargetUris());
        dto.setFlowRefreshed(group.getLastRefreshTime());
        dto.setContents(contents);
        dto.setTransportProtocol(group.getTransportProtocol().name());
        dto.setProxyHost(group.getProxyHost());
        dto.setProxyPort(group.getProxyPort());
        dto.setProxyUser(group.getProxyUser());
        if (!StringUtils.isEmpty(group.getProxyPassword())) {
            dto.setProxyPassword(SENSITIVE_VALUE_MASK);
        }

        // only specify the secure flag if we know the target system has site to site enabled
        if (group.isSiteToSiteEnabled()) {
            dto.setTargetSecure(group.getSecureFlag());
        }

        if (group.getAuthorizationIssue() != null) {
            dto.setAuthorizationIssues(Arrays.asList(group.getAuthorizationIssue()));
        }

        final Collection<ValidationResult> validationErrors = group.validate();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        dto.setLocalNetworkInterface(group.getNetworkInterface());

        dto.setActiveRemoteInputPortCount(activeRemoteInputPortCount);
        dto.setInactiveRemoteInputPortCount(inactiveRemoteInputPortCount);
        dto.setActiveRemoteOutputPortCount(activeRemoteOutputPortCount);
        dto.setInactiveRemoteOutputPortCount(inactiveRemoteOutputPortCount);
        dto.setVersionedComponentId(group.getVersionedComponentId().orElse(null));

        final RemoteProcessGroupCounts counts = group.getCounts();
        if (counts != null) {
            dto.setInputPortCount(counts.getInputPortCount());
            dto.setOutputPortCount(counts.getOutputPortCount());
        }

        return dto;
    }

    /**
     * Creates a FlowBreadcrumbEntity from the specified parent ProcessGroup.
     *
     * @param group group
     * @return dto
     */
    private FlowBreadcrumbEntity createBreadcrumbEntity(final ProcessGroup group) {
        if (group == null) {
            return null;
        }

        final FlowBreadcrumbDTO dto = createBreadcrumbDto(group);
        final PermissionsDTO permissions = createPermissionsDto(group);
        final FlowBreadcrumbEntity entity = entityFactory.createFlowBreadcrumbEntity(dto, permissions);

        if (group.getParent() != null) {
            entity.setParentBreadcrumb(createBreadcrumbEntity(group.getParent()));
        }

        return entity;
    }

    /**
     * Creates a FlowBreadcrumbDTO from the specified parent ProcessGroup.
     *
     * @param group group
     * @return dto
     */
    private FlowBreadcrumbDTO createBreadcrumbDto(final ProcessGroup group) {
        if (group == null) {
            return null;
        }

        final FlowBreadcrumbDTO dto = new FlowBreadcrumbDTO();
        dto.setId(group.getIdentifier());
        dto.setName(group.getName());

        final VersionControlInformationDTO versionControlInformation = createVersionControlInformationDto(group);
        dto.setVersionControlInformation(versionControlInformation);

        return dto;
    }

    public ComponentReferenceDTO createComponentReferenceDto(final Authorizable authorizable) {
        if (authorizable == null || !(authorizable instanceof ComponentAuthorizable)) {
            return null;
        }

        final ComponentAuthorizable componentAuthorizable = (ComponentAuthorizable) authorizable;
        final ComponentReferenceDTO dto = new ComponentReferenceDTO();
        dto.setId(componentAuthorizable.getIdentifier());
        dto.setParentGroupId(componentAuthorizable.getProcessGroupIdentifier());
        dto.setName(authorizable.getResource().getName());

        return dto;
    }

    public AccessPolicySummaryDTO createAccessPolicySummaryDto(final AccessPolicy accessPolicy, final ComponentReferenceEntity componentReference) {
        if (accessPolicy == null) {
            return null;
        }

        final AccessPolicySummaryDTO dto = new AccessPolicySummaryDTO();
        dto.setId(accessPolicy.getIdentifier());
        dto.setResource(accessPolicy.getResource());
        dto.setAction(accessPolicy.getAction().toString());
        dto.setConfigurable(AuthorizerCapabilityDetection.isAccessPolicyConfigurable(authorizer, accessPolicy));
        dto.setComponentReference(componentReference);
        return dto;
    }

    public AccessPolicyDTO createAccessPolicyDto(final AccessPolicy accessPolicy, final Set<TenantEntity> userGroups,
                                                 final Set<TenantEntity> users, final ComponentReferenceEntity componentReference) {

        if (accessPolicy == null) {
            return null;
        }

        final AccessPolicyDTO dto = new AccessPolicyDTO();
        dto.setUserGroups(userGroups);
        dto.setUsers(users);
        dto.setId(accessPolicy.getIdentifier());
        dto.setResource(accessPolicy.getResource());
        dto.setAction(accessPolicy.getAction().toString());
        dto.setConfigurable(AuthorizerCapabilityDetection.isAccessPolicyConfigurable(authorizer, accessPolicy));
        dto.setComponentReference(componentReference);
        return dto;
    }

    /**
     * Creates the PermissionsDTO based on the specified Authorizable.
     *
     * @param authorizable authorizable
     * @return dto
     */
    public PermissionsDTO createPermissionsDto(final Authorizable authorizable) {
        return createPermissionsDto(authorizable, NiFiUserUtils.getNiFiUser());
    }

    /**
     * Creates the PermissionsDTO based on the specified Authorizable for the given user
     *
     * @param authorizable authorizable
     * @param user the NiFi User for which the Permissions are being created
     * @return dto
     */
    public PermissionsDTO createPermissionsDto(final Authorizable authorizable, final NiFiUser user) {
        final PermissionsDTO dto = new PermissionsDTO();
        dto.setCanRead(authorizable.isAuthorized(authorizer, RequestAction.READ, user));
        dto.setCanWrite(authorizable.isAuthorized(authorizer, RequestAction.WRITE, user));
        return dto;
    }

    public AffectedComponentEntity createAffectedComponentEntity(final ProcessorEntity processorEntity) {
        if (processorEntity == null) {
            return null;
        }

        final AffectedComponentEntity component = new AffectedComponentEntity();
        component.setBulletins(processorEntity.getBulletins());
        component.setId(processorEntity.getId());
        component.setPermissions(processorEntity.getPermissions());
        component.setPosition(processorEntity.getPosition());
        component.setRevision(processorEntity.getRevision());
        component.setUri(processorEntity.getUri());

        final ProcessorDTO processorDto = processorEntity.getComponent();
        final AffectedComponentDTO componentDto = new AffectedComponentDTO();
        if (componentDto == null) {
            componentDto.setId(processorEntity.getId());
            componentDto.setName(processorEntity.getId());
        } else {
            componentDto.setId(processorDto.getId());
            componentDto.setName(processorDto.getName());
            componentDto.setProcessGroupId(processorDto.getParentGroupId());
            componentDto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_PROCESSOR);
            componentDto.setState(processorDto.getState());
            componentDto.setValidationErrors(processorDto.getValidationErrors());
        }
        component.setComponent(componentDto);

        return component;
    }

    public AffectedComponentEntity createAffectedComponentEntity(final PortEntity portEntity, final String referenceType) {
        if (portEntity == null) {
            return null;
        }

        final AffectedComponentEntity component = new AffectedComponentEntity();
        component.setBulletins(portEntity.getBulletins());
        component.setId(portEntity.getId());
        component.setPermissions(portEntity.getPermissions());
        component.setPosition(portEntity.getPosition());
        component.setRevision(portEntity.getRevision());
        component.setUri(portEntity.getUri());

        final PortDTO portDto = portEntity.getComponent();
        final AffectedComponentDTO componentDto = new AffectedComponentDTO();
        if (componentDto == null) {
            componentDto.setId(portEntity.getId());
            componentDto.setName(portEntity.getId());
        } else {
            componentDto.setId(portDto.getId());
            componentDto.setName(portDto.getName());
            componentDto.setProcessGroupId(portDto.getParentGroupId());
            componentDto.setReferenceType(referenceType);
            componentDto.setState(portDto.getState());
            componentDto.setValidationErrors(portDto.getValidationErrors());
        }

        component.setComponent(componentDto);

        return component;
    }

    public AffectedComponentEntity createAffectedComponentEntity(final ControllerServiceEntity serviceEntity) {
        if (serviceEntity == null) {
            return null;
        }

        final AffectedComponentEntity component = new AffectedComponentEntity();
        component.setBulletins(serviceEntity.getBulletins());
        component.setId(serviceEntity.getId());
        component.setPermissions(serviceEntity.getPermissions());
        component.setPosition(serviceEntity.getPosition());
        component.setRevision(serviceEntity.getRevision());
        component.setUri(serviceEntity.getUri());

        final ControllerServiceDTO serviceDto = serviceEntity.getComponent();
        final AffectedComponentDTO componentDto = new AffectedComponentDTO();
        if (serviceDto == null) {
            componentDto.setId(serviceEntity.getId());
            componentDto.setName(serviceEntity.getId());
            componentDto.setProcessGroupId(serviceEntity.getParentGroupId());
        } else {
            componentDto.setId(serviceDto.getId());
            componentDto.setName(serviceDto.getName());
            componentDto.setProcessGroupId(serviceDto.getParentGroupId());
            componentDto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_CONTROLLER_SERVICE);
            componentDto.setState(serviceDto.getState());
            componentDto.setValidationErrors(serviceDto.getValidationErrors());
        }

        component.setComponent(componentDto);

        return component;
    }

    public AffectedComponentEntity createAffectedComponentEntity(final RemoteProcessGroupPortDTO remotePortDto, final String referenceType, final RemoteProcessGroupEntity rpgEntity) {
        if (remotePortDto == null) {
            return null;
        }

        final AffectedComponentEntity component = new AffectedComponentEntity();
        component.setId(remotePortDto.getId());
        component.setPermissions(rpgEntity.getPermissions());
        component.setRevision(rpgEntity.getRevision());
        component.setUri(rpgEntity.getUri());

        final AffectedComponentDTO componentDto = new AffectedComponentDTO();
        componentDto.setId(remotePortDto.getId());
        componentDto.setName(remotePortDto.getName());
        componentDto.setProcessGroupId(remotePortDto.getGroupId());
        componentDto.setReferenceType(referenceType);
        componentDto.setState(remotePortDto.isTransmitting() ? "Running" : "Stopped");
        component.setComponent(componentDto);

        return component;
    }


    public AffectedComponentDTO createAffectedComponentDto(final ComponentNode component) {
        final AffectedComponentDTO dto = new AffectedComponentDTO();
        dto.setId(component.getIdentifier());
        dto.setName(component.getName());
        dto.setProcessGroupId(component.getProcessGroupIdentifier());

        if (component instanceof ProcessorNode) {
            final ProcessorNode node = ((ProcessorNode) component);
            dto.setState(node.getDesiredState().name());
            dto.setActiveThreadCount(node.getActiveThreadCount());
            dto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_PROCESSOR);
        } else if (component instanceof ControllerServiceNode) {
            final ControllerServiceNode node = ((ControllerServiceNode) component);
            dto.setState(node.getState().name());
            dto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_CONTROLLER_SERVICE);
        }

        final Collection<ValidationResult> validationErrors = component.getValidationErrors();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        return dto;
    }

    public ComponentValidationResultDTO createComponentValidationResultDto(final ComponentNode component, final ValidationState validationResults) {
        final ComponentValidationResultDTO dto = new ComponentValidationResultDTO();
        dto.setId(component.getIdentifier());
        dto.setName(component.getName());
        dto.setProcessGroupId(component.getProcessGroupIdentifier());

        if (component instanceof ProcessorNode) {
            final ProcessorNode node = ((ProcessorNode) component);
            dto.setState(node.getScheduledState().name());
            dto.setActiveThreadCount(node.getActiveThreadCount());
            dto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_PROCESSOR);
        } else if (component instanceof ControllerServiceNode) {
            final ControllerServiceNode node = ((ControllerServiceNode) component);
            dto.setState(node.getState().name());
            dto.setReferenceType(AffectedComponentDTO.COMPONENT_TYPE_CONTROLLER_SERVICE);
        }

        final Collection<ValidationResult> validationErrors = component.getValidationErrors();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
            dto.setCurrentlyValid(false);
        } else {
            dto.setCurrentlyValid(true);
        }

        final List<String> resultantValidationErrors = validationResults.getValidationErrors().stream()
            .map(ValidationResult::toString)
            .collect(Collectors.toList());

        dto.setResultantValidationErrors(resultantValidationErrors);
        dto.setResultsValid(resultantValidationErrors.isEmpty());

        return dto;
    }

    /**
     * Creates a ProcessGroupDTO from the specified ProcessGroup.
     *
     * @param group group
     * @return dto
     */
    public ProcessGroupDTO createProcessGroupDto(final ProcessGroup group) {
        return createProcessGroupDto(group, false);
    }

    public ProcessGroupFlowDTO createProcessGroupFlowDto(final ProcessGroup group, final ProcessGroupStatus groupStatus, final RevisionManager revisionManager,
                                                         final Function<ProcessGroup, List<BulletinEntity>> getProcessGroupBulletins) {

        final ProcessGroupFlowDTO dto = new ProcessGroupFlowDTO();
        dto.setId(group.getIdentifier());
        dto.setLastRefreshed(new Date());
        dto.setBreadcrumb(createBreadcrumbEntity(group));
        dto.setFlow(createFlowDto(group, groupStatus, revisionManager, getProcessGroupBulletins));

        final ProcessGroup parent = group.getParent();
        if (parent != null) {
            dto.setParentGroupId(parent.getIdentifier());
        }

        final ParameterContext parameterContext = group.getParameterContext();
        if (parameterContext != null) {
            dto.setParameterContext(entityFactory.createParameterReferenceEntity(createParameterContextReference(parameterContext), createPermissionsDto(parameterContext)));
        }
        return dto;
    }

    public ParameterContextReferenceDTO createParameterContextReference(final ParameterContext parameterContext) {
        if (parameterContext == null) {
            return null;
        }

        final ParameterContextReferenceDTO dto = new ParameterContextReferenceDTO();
        dto.setId(parameterContext.getIdentifier());
        dto.setName(parameterContext.getName());

        return dto;
    }

    public FlowDTO createFlowDto(final ProcessGroup group, final ProcessGroupStatus groupStatus, final FlowSnippetDTO snippet, final RevisionManager revisionManager,
                                 final Function<ProcessGroup, List<BulletinEntity>> getProcessGroupBulletins) {
        if (snippet == null) {
            return null;
        }

        final FlowDTO flow = new FlowDTO();

        for (final ConnectionDTO snippetConnection : snippet.getConnections()) {
            final Connection connection = group.getConnection(snippetConnection.getId());

            // marshal the actual connection as the snippet is pruned
            final ConnectionDTO dto = createConnectionDto(connection);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(connection.getIdentifier()));
            final PermissionsDTO accessPolicy = createPermissionsDto(connection);
            final ConnectionStatusDTO status = getComponentStatus(
                () -> groupStatus.getConnectionStatus().stream().filter(connectionStatus -> connection.getIdentifier().equals(connectionStatus.getId())).findFirst().orElse(null),
                this::createConnectionStatusDto
            );
            flow.getConnections().add(entityFactory.createConnectionEntity(dto, revision, accessPolicy, status));
        }

        for (final FunnelDTO snippetFunnel : snippet.getFunnels()) {
            final Funnel funnel = group.getFunnel(snippetFunnel.getId());

            // marshal the actual funnel as the snippet is pruned
            final FunnelDTO dto = createFunnelDto(funnel);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(funnel.getIdentifier()));
            final PermissionsDTO accessPolicy = createPermissionsDto(funnel);
            flow.getFunnels().add(entityFactory.createFunnelEntity(dto, revision, accessPolicy));
        }

        for (final PortDTO snippetInputPort : snippet.getInputPorts()) {
            final Port inputPort = group.getInputPort(snippetInputPort.getId());

            // marshal the actual port as the snippet is pruned
            final PortDTO dto = createPortDto(inputPort);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(inputPort.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(inputPort);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(inputPort));
            final PortStatusDTO status = getComponentStatus(
                () -> groupStatus.getInputPortStatus().stream().filter(inputPortStatus -> inputPort.getIdentifier().equals(inputPortStatus.getId())).findFirst().orElse(null),
                inputPortStatus -> createPortStatusDto(inputPortStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(inputPort.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            flow.getInputPorts().add(entityFactory.createPortEntity(dto, revision, permissions, operatePermissions, status, bulletinEntities));
        }

        for (final PortDTO snippetOutputPort : snippet.getOutputPorts()) {
            final Port outputPort = group.getOutputPort(snippetOutputPort.getId());

            // marshal the actual port as the snippet is pruned
            final PortDTO dto = createPortDto(outputPort);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(outputPort.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(outputPort);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(outputPort));
            final PortStatusDTO status = getComponentStatus(
                () -> groupStatus.getOutputPortStatus().stream().filter(outputPortStatus -> outputPort.getIdentifier().equals(outputPortStatus.getId())).findFirst().orElse(null),
                outputPortStatus -> createPortStatusDto(outputPortStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(outputPort.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            flow.getOutputPorts().add(entityFactory.createPortEntity(dto, revision, permissions, operatePermissions, status, bulletinEntities));
        }

        for (final LabelDTO snippetLabel : snippet.getLabels()) {
            final Label label = group.getLabel(snippetLabel.getId());

            // marshal the actual label as the snippet is pruned
            final LabelDTO dto = createLabelDto(label);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(label.getIdentifier()));
            final PermissionsDTO accessPolicy = createPermissionsDto(label);
            flow.getLabels().add(entityFactory.createLabelEntity(dto, revision, accessPolicy));
        }

        for (final ProcessGroupDTO snippetProcessGroup : snippet.getProcessGroups()) {
            final ProcessGroup processGroup = group.getProcessGroup(snippetProcessGroup.getId());

            // marshal the actual group as the snippet is pruned
            final ProcessGroupDTO dto = createProcessGroupDto(processGroup);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(processGroup.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(processGroup);
            final ProcessGroupStatusDTO status = getComponentStatus(
                () -> groupStatus.getProcessGroupStatus().stream().filter(processGroupStatus -> processGroup.getIdentifier().equals(processGroupStatus.getId())).findFirst().orElse(null),
                processGroupStatus -> createConciseProcessGroupStatusDto(processGroupStatus)
            );
            final List<BulletinEntity> bulletins = getProcessGroupBulletins.apply(processGroup);
            flow.getProcessGroups().add(entityFactory.createProcessGroupEntity(dto, revision, permissions, status, bulletins));
        }

        for (final ProcessorDTO snippetProcessor : snippet.getProcessors()) {
            final ProcessorNode processor = group.getProcessor(snippetProcessor.getId());

            // marshal the actual processor as the snippet is pruned
            final ProcessorDTO dto = createProcessorDto(processor);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(processor.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(processor);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(processor));
            final ProcessorStatusDTO status = getComponentStatus(
                () -> groupStatus.getProcessorStatus().stream().filter(processorStatus -> processor.getIdentifier().equals(processorStatus.getId())).findFirst().orElse(null),
                processorStatus -> createProcessorStatusDto(processorStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(processor.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            flow.getProcessors().add(entityFactory.createProcessorEntity(dto, revision, permissions, operatePermissions, status, bulletinEntities));
        }

        for (final RemoteProcessGroupDTO snippetRemoteProcessGroup : snippet.getRemoteProcessGroups()) {
            final RemoteProcessGroup remoteProcessGroup = group.getRemoteProcessGroup(snippetRemoteProcessGroup.getId());

            // marshal the actual rpm as the snippet is pruned
            final RemoteProcessGroupDTO dto = createRemoteProcessGroupDto(remoteProcessGroup);
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(remoteProcessGroup.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(remoteProcessGroup);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(remoteProcessGroup));
            final RemoteProcessGroupStatusDTO status = getComponentStatus(
                () -> groupStatus.getRemoteProcessGroupStatus().stream().filter(rpgStatus -> remoteProcessGroup.getIdentifier().equals(rpgStatus.getId())).findFirst().orElse(null),
                remoteProcessGroupStatus -> createRemoteProcessGroupStatusDto(remoteProcessGroup, remoteProcessGroupStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(remoteProcessGroup.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            flow.getRemoteProcessGroups().add(entityFactory.createRemoteProcessGroupEntity(dto, revision, permissions, operatePermissions, status, bulletinEntities));
        }

        return flow;
    }

    private <T, S> T getComponentStatus(final Supplier<S> getComponentStatus, final Function<S, T> convertToDto) {
        final T statusDTO;
        final S status = getComponentStatus.get();
        if (status != null) {
            statusDTO = convertToDto.apply(status);
        } else {
            statusDTO = null;
        }
        return statusDTO;
    }

    public FlowDTO createFlowDto(final ProcessGroup group, final ProcessGroupStatus groupStatus, final RevisionManager revisionManager,
                                 final Function<ProcessGroup, List<BulletinEntity>> getProcessGroupBulletins) {
        final FlowDTO dto = new FlowDTO();

        for (final ProcessorNode procNode : group.getProcessors()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(procNode.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(procNode);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(procNode));
            final ProcessorStatusDTO status = getComponentStatus(
                () -> groupStatus.getProcessorStatus().stream().filter(processorStatus -> procNode.getIdentifier().equals(processorStatus.getId())).findFirst().orElse(null),
                processorStatus -> createProcessorStatusDto(processorStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(procNode.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            dto.getProcessors().add(entityFactory.createProcessorEntity(createProcessorDto(procNode), revision, permissions, operatePermissions, status, bulletinEntities));
        }

        for (final Connection connNode : group.getConnections()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(connNode.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(connNode);
            final ConnectionStatusDTO status = getComponentStatus(
                () -> groupStatus.getConnectionStatus().stream().filter(connectionStatus -> connNode.getIdentifier().equals(connectionStatus.getId())).findFirst().orElse(null),
                connectionStatus -> createConnectionStatusDto(connectionStatus)
            );
            dto.getConnections().add(entityFactory.createConnectionEntity(createConnectionDto(connNode), revision, permissions, status));
        }

        for (final Label label : group.getLabels()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(label.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(label);
            dto.getLabels().add(entityFactory.createLabelEntity(createLabelDto(label), revision, permissions));
        }

        for (final Funnel funnel : group.getFunnels()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(funnel.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(funnel);
            dto.getFunnels().add(entityFactory.createFunnelEntity(createFunnelDto(funnel), revision, permissions));
        }

        for (final ProcessGroup childGroup : group.getProcessGroups()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(childGroup.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(childGroup);
            final ProcessGroupStatusDTO status = getComponentStatus(
                () -> groupStatus.getProcessGroupStatus().stream().filter(processGroupStatus -> childGroup.getIdentifier().equals(processGroupStatus.getId())).findFirst().orElse(null),
                processGroupStatus -> createConciseProcessGroupStatusDto(processGroupStatus)
            );
            final List<BulletinEntity> bulletins = getProcessGroupBulletins.apply(childGroup);
            dto.getProcessGroups().add(entityFactory.createProcessGroupEntity(createProcessGroupDto(childGroup), revision, permissions, status, bulletins));
        }

        for (final RemoteProcessGroup rpg : group.getRemoteProcessGroups()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(rpg.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(rpg);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(rpg));
            final RemoteProcessGroupStatusDTO status = getComponentStatus(
                () -> groupStatus.getRemoteProcessGroupStatus().stream().filter(remoteProcessGroupStatus -> rpg.getIdentifier().equals(remoteProcessGroupStatus.getId())).findFirst().orElse(null),
                remoteProcessGroupStatus -> createRemoteProcessGroupStatusDto(rpg, remoteProcessGroupStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(rpg.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            dto.getRemoteProcessGroups().add(entityFactory.createRemoteProcessGroupEntity(createRemoteProcessGroupDto(rpg), revision, permissions, operatePermissions, status, bulletinEntities));
        }

        for (final Port inputPort : group.getInputPorts()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(inputPort.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(inputPort);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(inputPort));
            final PortStatusDTO status = getComponentStatus(
                () -> groupStatus.getInputPortStatus().stream().filter(inputPortStatus -> inputPort.getIdentifier().equals(inputPortStatus.getId())).findFirst().orElse(null),
                inputPortStatus -> createPortStatusDto(inputPortStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(inputPort.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            dto.getInputPorts().add(entityFactory.createPortEntity(createPortDto(inputPort), revision, permissions, operatePermissions, status, bulletinEntities));
        }

        for (final Port outputPort : group.getOutputPorts()) {
            final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(outputPort.getIdentifier()));
            final PermissionsDTO permissions = createPermissionsDto(outputPort);
            final PermissionsDTO operatePermissions = createPermissionsDto(new OperationAuthorizable(outputPort));
            final PortStatusDTO status = getComponentStatus(
                () -> groupStatus.getOutputPortStatus().stream().filter(outputPortStatus -> outputPort.getIdentifier().equals(outputPortStatus.getId())).findFirst().orElse(null),
                outputPortStatus -> createPortStatusDto(outputPortStatus)
            );
            final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(outputPort.getIdentifier()));
            final List<BulletinEntity> bulletinEntities = bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin, permissions.getCanRead())).collect(Collectors.toList());
            dto.getOutputPorts().add(entityFactory.createPortEntity(createPortDto(outputPort), revision, permissions, operatePermissions, status, bulletinEntities));
        }

        return dto;
    }

    /**
     * Creates a ProcessGroupDTO from the specified ProcessGroup.
     *
     * @param group group
     * @param recurse recurse
     * @return dto
     */
    public ProcessGroupDTO createProcessGroupDto(final ProcessGroup group, final boolean recurse) {
        final ProcessGroupDTO dto = createConciseProcessGroupDto(group);
        dto.setContents(createProcessGroupContentsDto(group, recurse));
        return dto;
    }

    /**
     * Creates a ProcessGroupDTO from the specified ProcessGroup.
     *
     * @param group group
     * @return dto
     */
    private ProcessGroupDTO createConciseProcessGroupDto(final ProcessGroup group) {
        if (group == null) {
            return null;
        }

        final ProcessGroupDTO dto = new ProcessGroupDTO();
        dto.setId(group.getIdentifier());
        dto.setPosition(createPositionDto(group.getPosition()));
        dto.setComments(group.getComments());
        dto.setName(group.getName());
        dto.setVersionedComponentId(group.getVersionedComponentId().orElse(null));
        dto.setVersionControlInformation(createVersionControlInformationDto(group));
        dto.setFlowfileConcurrency(group.getFlowFileConcurrency().name());
        dto.setFlowfileOutboundPolicy(group.getFlowFileOutboundPolicy().name());

        final ParameterContext parameterContext = group.getParameterContext();
        if (parameterContext != null) {
            dto.setParameterContext(entityFactory.createParameterReferenceEntity(createParameterContextReference(parameterContext), createPermissionsDto(parameterContext)));
        }

        final Map<String, String> variables = group.getVariableRegistry().getVariableMap().entrySet().stream()
            .collect(Collectors.toMap(entry -> entry.getKey().getName(), Entry::getValue));
        dto.setVariables(variables);

        final ProcessGroup parentGroup = group.getParent();
        if (parentGroup != null) {
            dto.setParentGroupId(parentGroup.getIdentifier());
        }

        final ProcessGroupCounts counts = group.getCounts();
        dto.setRunningCount(counts.getRunningCount());
        dto.setStoppedCount(counts.getStoppedCount());
        dto.setInvalidCount(counts.getInvalidCount());
        dto.setDisabledCount(counts.getDisabledCount());
        dto.setLocalInputPortCount(counts.getLocalInputPortCount());
        dto.setLocalOutputPortCount(counts.getLocalOutputPortCount());
        dto.setPublicInputPortCount(counts.getPublicInputPortCount());
        dto.setPublicOutputPortCount(counts.getPublicOutputPortCount());
        dto.setActiveRemotePortCount(counts.getActiveRemotePortCount());
        dto.setInactiveRemotePortCount(counts.getInactiveRemotePortCount());
        dto.setUpToDateCount(counts.getUpToDateCount());
        dto.setLocallyModifiedCount(counts.getLocallyModifiedCount());
        dto.setStaleCount(counts.getStaleCount());
        dto.setLocallyModifiedAndStaleCount(counts.getLocallyModifiedAndStaleCount());
        dto.setSyncFailureCount(counts.getSyncFailureCount());

        return dto;
    }


    public Set<ComponentDifferenceDTO> createComponentDifferenceDtos(final FlowComparison comparison, final FlowManager flowManager) {
        final Map<ComponentDifferenceDTO, List<DifferenceDTO>> differencesByComponent = new HashMap<>();

        final Map<String, VersionedProcessGroup> versionedGroups = flattenProcessGroups(comparison.getFlowA().getContents());

        for (final FlowDifference difference : comparison.getDifferences()) {
            // Ignore these as local differences for now because we can't do anything with it
            if (difference.getDifferenceType() == DifferenceType.BUNDLE_CHANGED) {
                continue;
            }

            // Ignore differences that are the result of the Versioned Flow not having a Scheduled State and the newer flow being "ENABLED". We do this because
            // Scheduled State was not always part of the Versioned Flow - it was always assumed to be ENABLED. We don't want flows that were previously stored in this
            // format to now be considered different than the local flow.
            if (FlowDifferenceFilters.isScheduledStateNew(difference)) {
                continue;
            }

            // Ignore differences for adding remote ports
            if (FlowDifferenceFilters.isAddedOrRemovedRemotePort(difference)) {
                continue;
            }

            // Ignore name changes to public ports
            if (FlowDifferenceFilters.isPublicPortNameChange(difference)) {
                continue;
            }

            if (FlowDifferenceFilters.isIgnorableVersionedFlowCoordinateChange(difference)) {
                continue;
            }

            if (FlowDifferenceFilters.isNewPropertyWithDefaultValue(difference, flowManager)) {
                continue;
            }

            final VersionedComponent componentA = difference.getComponentA();
            final VersionedProcessGroup relevantProcessGroup = componentA == null ? null : versionedGroups.get(componentA.getGroupIdentifier());
            if (relevantProcessGroup != null && FlowDifferenceFilters.isNewRelationshipAutoTerminatedAndDefaulted(difference, relevantProcessGroup, flowManager)) {
                continue;
            }

            final ComponentDifferenceDTO componentDiff = createComponentDifference(difference);
            final List<DifferenceDTO> differences = differencesByComponent.computeIfAbsent(componentDiff, key -> new ArrayList<>());

            final DifferenceDTO dto = new DifferenceDTO();
            dto.setDifferenceType(difference.getDifferenceType().getDescription());
            dto.setDifference(difference.getDescription());

            differences.add(dto);
        }

        for (final Map.Entry<ComponentDifferenceDTO, List<DifferenceDTO>> entry : differencesByComponent.entrySet()) {
            entry.getKey().setDifferences(entry.getValue());
        }

        return differencesByComponent.keySet();
    }

    private Map<String, VersionedProcessGroup> flattenProcessGroups(final VersionedProcessGroup group) {
        final Map<String, VersionedProcessGroup> flattened = new HashMap<>();
        flattenProcessGroups(group, flattened);
        return flattened;
    }

    private void flattenProcessGroups(final VersionedProcessGroup group, final Map<String, VersionedProcessGroup> flattened) {
        flattened.put(group.getIdentifier(), group);

        for (final VersionedProcessGroup child : group.getProcessGroups()) {
            flattenProcessGroups(child, flattened);
        }
    }

    private ComponentDifferenceDTO createComponentDifference(final FlowDifference difference) {
        VersionedComponent component = difference.getComponentA();
        if (component == null || difference.getComponentB() instanceof InstantiatedVersionedComponent) {
            component = difference.getComponentB();
        }

        final ComponentDifferenceDTO dto = new ComponentDifferenceDTO();
        dto.setComponentName(component.getName());
        dto.setComponentType(component.getComponentType().toString());

        if (component instanceof InstantiatedVersionedComponent) {
            final InstantiatedVersionedComponent instantiatedComponent = (InstantiatedVersionedComponent) component;
            dto.setComponentId(instantiatedComponent.getInstanceId());
            dto.setProcessGroupId(instantiatedComponent.getInstanceGroupId());
        } else {
            dto.setComponentId(component.getIdentifier());
            dto.setProcessGroupId(dto.getProcessGroupId());
        }

        return dto;
    }


    public VersionControlInformationDTO createVersionControlInformationDto(final ProcessGroup group) {
        if (group == null) {
            return null;
        }

        final VersionControlInformation versionControlInfo = group.getVersionControlInformation();
        if (versionControlInfo == null) {
            return null;
        }

        final VersionControlInformationDTO dto = new VersionControlInformationDTO();
        dto.setGroupId(group.getIdentifier());
        dto.setRegistryId(versionControlInfo.getRegistryIdentifier());
        dto.setRegistryName(versionControlInfo.getRegistryName());
        dto.setBucketId(versionControlInfo.getBucketIdentifier());
        dto.setBucketName(versionControlInfo.getBucketName());
        dto.setFlowId(versionControlInfo.getFlowIdentifier());
        dto.setFlowName(versionControlInfo.getFlowName());
        dto.setFlowDescription(versionControlInfo.getFlowDescription());
        dto.setVersion(versionControlInfo.getVersion());

        final VersionedFlowStatus status = versionControlInfo.getStatus();
        final VersionedFlowState state = status.getState();
        dto.setState(state == null ? null : state.name());
        dto.setStateExplanation(status.getStateExplanation());

        return dto;
    }

    public Map<String, String> createVersionControlComponentMappingDto(final InstantiatedVersionedProcessGroup group) {
        final Map<String, String> mapping = new HashMap<>();

        mapping.put(group.getInstanceId(), group.getIdentifier());
        group.getProcessors().stream()
            .map(proc -> (InstantiatedVersionedProcessor) proc)
            .forEach(proc -> mapping.put(proc.getInstanceId(), proc.getIdentifier()));
        group.getFunnels().stream()
            .map(funnel -> (InstantiatedVersionedFunnel) funnel)
            .forEach(funnel -> mapping.put(funnel.getInstanceId(), funnel.getIdentifier()));
        group.getInputPorts().stream()
            .map(port -> (InstantiatedVersionedPort) port)
            .forEach(port -> mapping.put(port.getInstanceId(), port.getIdentifier()));
        group.getOutputPorts().stream()
            .map(port -> (InstantiatedVersionedPort) port)
            .forEach(port -> mapping.put(port.getInstanceId(), port.getIdentifier()));
        group.getControllerServices().stream()
            .map(service -> (InstantiatedVersionedControllerService) service)
            .forEach(service -> mapping.put(service.getInstanceId(), service.getIdentifier()));
        group.getLabels().stream()
            .map(label -> (InstantiatedVersionedLabel) label)
            .forEach(label -> mapping.put(label.getInstanceId(), label.getIdentifier()));
        group.getConnections().stream()
            .map(conn -> (InstantiatedVersionedConnection) conn)
            .forEach(conn -> mapping.put(conn.getInstanceId(), conn.getIdentifier()));
        group.getRemoteProcessGroups().stream()
            .map(rpg -> (InstantiatedVersionedRemoteProcessGroup) rpg)
            .forEach(rpg -> {
                mapping.put(rpg.getInstanceId(), rpg.getIdentifier());

                if (rpg.getInputPorts() != null) {
                    rpg.getInputPorts().stream()
                        .map(port -> (InstantiatedVersionedRemoteGroupPort) port)
                        .forEach(port -> mapping.put(port.getInstanceId(), port.getIdentifier()));
                }

                if (rpg.getOutputPorts() != null) {
                    rpg.getOutputPorts().stream()
                        .map(port -> (InstantiatedVersionedRemoteGroupPort) port)
                        .forEach(port -> mapping.put(port.getInstanceId(), port.getIdentifier()));
                }
            });

        group.getProcessGroups().stream()
            .map(child -> (InstantiatedVersionedProcessGroup) child)
            .forEach(child -> {
                final Map<String, String> childMapping = createVersionControlComponentMappingDto(child);
                mapping.putAll(childMapping);
            });

        return mapping;
    }


    /**
     * Creates a ProcessGroupContentDTO from the specified ProcessGroup.
     *
     * @param group group
     * @param recurse recurse
     * @return dto
     */
    private FlowSnippetDTO createProcessGroupContentsDto(final ProcessGroup group, final boolean recurse) {
        if (group == null) {
            return null;
        }

        final FlowSnippetDTO dto = new FlowSnippetDTO();

        for (final ProcessorNode procNode : group.getProcessors()) {
            dto.getProcessors().add(createProcessorDto(procNode));
        }

        for (final Connection connNode : group.getConnections()) {
            dto.getConnections().add(createConnectionDto(connNode));
        }

        for (final Label label : group.getLabels()) {
            dto.getLabels().add(createLabelDto(label));
        }

        for (final Funnel funnel : group.getFunnels()) {
            dto.getFunnels().add(createFunnelDto(funnel));
        }

        for (final ProcessGroup childGroup : group.getProcessGroups()) {
            if (recurse) {
                dto.getProcessGroups().add(createProcessGroupDto(childGroup, recurse));
            } else {
                dto.getProcessGroups().add(createConciseProcessGroupDto(childGroup));
            }
        }

        for (final RemoteProcessGroup remoteProcessGroup : group.getRemoteProcessGroups()) {
            dto.getRemoteProcessGroups().add(createRemoteProcessGroupDto(remoteProcessGroup));
        }

        for (final Port inputPort : group.getInputPorts()) {
            dto.getInputPorts().add(createPortDto(inputPort));
        }

        for (final Port outputPort : group.getOutputPorts()) {
            dto.getOutputPorts().add(createPortDto(outputPort));
        }

        return dto;
    }

    private boolean isRestricted(final Class<?> cls) {
        return cls.isAnnotationPresent(Restricted.class);
    }

    private String getUsageRestriction(final Class<?> cls) {
        final Restricted restricted = cls.getAnnotation(Restricted.class);

        if (restricted == null) {
            return null;
        }

        if (StringUtils.isBlank(restricted.value())) {
            return null;
        }

        return restricted.value();
    }

    private Set<ExplicitRestrictionDTO> getExplicitRestrictions(final Class<?> cls) {
        final Restricted restricted = cls.getAnnotation(Restricted.class);

        if (restricted == null) {
            return null;
        }

        final Restriction[] restrictions = restricted.restrictions();

        if (restrictions == null || restrictions.length == 0) {
            return null;
        }

        return Arrays.stream(restrictions).map(restriction -> {
            final RequiredPermissionDTO requiredPermission = new RequiredPermissionDTO();
            requiredPermission.setId(restriction.requiredPermission().getPermissionIdentifier());
            requiredPermission.setLabel(restriction.requiredPermission().getPermissionLabel());

            final ExplicitRestrictionDTO usageRestriction = new ExplicitRestrictionDTO();
            usageRestriction.setRequiredPermission(requiredPermission);
            usageRestriction.setExplanation(restriction.explanation());
            return usageRestriction;
        }).collect(Collectors.toSet());
    }

    private String getDeprecationReason(final Class<?> cls) {
        final DeprecationNotice deprecationNotice = cls.getAnnotation(DeprecationNotice.class);
        return deprecationNotice == null ? null : deprecationNotice.reason();
    }

    public Set<AffectedComponentEntity> createAffectedComponentEntities(final Set<ComponentNode> affectedComponents, final RevisionManager revisionManager) {
        return affectedComponents.stream()
                .map(component -> createAffectedComponentEntity(component, revisionManager))
                .collect(Collectors.toSet());
    }

    public AffectedComponentEntity createAffectedComponentEntity(final ComponentNode componentNode, final RevisionManager revisionManager) {
        final AffectedComponentDTO affectedComponent = createAffectedComponentDto(componentNode);
        final PermissionsDTO permissions = createPermissionsDto(componentNode);
        final RevisionDTO revision = createRevisionDTO(revisionManager.getRevision(componentNode.getIdentifier()));

        final ProcessGroupNameDTO groupNameDto = new ProcessGroupNameDTO();
        groupNameDto.setId(componentNode.getProcessGroupIdentifier());
        groupNameDto.setName(componentNode.getProcessGroupIdentifier());

        ProcessGroup processGroup = null;
        if (componentNode instanceof ProcessorNode) {
            processGroup = ((ProcessorNode) componentNode).getProcessGroup();
        } else if (componentNode instanceof ControllerServiceNode) {
            processGroup = ((ControllerServiceNode) componentNode).getProcessGroup();
        }

        if (processGroup != null) {
            final boolean authorized = processGroup.isAuthorized(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
            if (authorized) {
                groupNameDto.setName(processGroup.getName());
            }
        }

        final List<BulletinDTO> bulletins = createBulletins(componentNode);
        return entityFactory.createAffectedComponentEntity(affectedComponent, revision, permissions, groupNameDto, bulletins);
    }

    private List<BulletinDTO> createBulletins(final ComponentNode componentNode) {
        final List<BulletinDTO> bulletins = createBulletinDtos(bulletinRepository.findBulletinsForSource(componentNode.getIdentifier()));
        return bulletins;
    }

    public VariableRegistryDTO createVariableRegistryDto(final ProcessGroup processGroup, final RevisionManager revisionManager) {
        final ComponentVariableRegistry variableRegistry = processGroup.getVariableRegistry();

        final List<String> variableNames = variableRegistry.getVariableMap().keySet().stream()
            .map(VariableDescriptor::getName)
            .collect(Collectors.toList());

        final Set<VariableEntity> variableEntities = new LinkedHashSet<>();

        for (final String variableName : variableNames) {
            final VariableDTO variableDto = new VariableDTO();
            variableDto.setName(variableName);
            variableDto.setValue(variableRegistry.getVariableValue(variableName));
            variableDto.setProcessGroupId(processGroup.getIdentifier());

            final Set<AffectedComponentEntity> affectedComponentEntities = createAffectedComponentEntities(processGroup.getComponentsAffectedByVariable(variableName), revisionManager);

            variableDto.setAffectedComponents(affectedComponentEntities);

            final boolean canWrite = isWritable(affectedComponentEntities);
            final VariableEntity variableEntity = new VariableEntity();
            variableEntity.setVariable(variableDto);
            variableEntity.setCanWrite(canWrite);

            variableEntities.add(variableEntity);
        }

        final VariableRegistryDTO registryDto = new VariableRegistryDTO();
        registryDto.setProcessGroupId(processGroup.getIdentifier());
        registryDto.setVariables(variableEntities);

        return registryDto;
    }

    private boolean isWritable(final Collection<AffectedComponentEntity> affectedComponentEntities) {
        for (final AffectedComponentEntity affectedComponent : affectedComponentEntities) {
            final PermissionsDTO permissions = affectedComponent.getPermissions();
            if (!permissions.getCanRead() || !permissions.getCanWrite()) {
                return false;
            }
        }

        return true;
    }

    public VariableRegistryUpdateRequestDTO createVariableRegistryUpdateRequestDto(final VariableRegistryUpdateRequest request) {
        final VariableRegistryUpdateRequestDTO dto = new VariableRegistryUpdateRequestDTO();
        dto.setComplete(request.isComplete());
        dto.setFailureReason(request.getFailureReason());
        dto.setLastUpdated(request.getLastUpdated());
        dto.setProcessGroupId(request.getProcessGroupId());
        dto.setRequestId(request.getRequestId());
        dto.setSubmissionTime(request.getSubmissionTime());

        final List<VariableRegistryUpdateStepDTO> updateSteps = new ArrayList<>();
        updateSteps.add(createVariableRegistryUpdateStepDto(request.getIdentifyRelevantComponentsStep()));
        updateSteps.add(createVariableRegistryUpdateStepDto(request.getStopProcessorsStep()));
        updateSteps.add(createVariableRegistryUpdateStepDto(request.getDisableServicesStep()));
        updateSteps.add(createVariableRegistryUpdateStepDto(request.getApplyUpdatesStep()));
        updateSteps.add(createVariableRegistryUpdateStepDto(request.getEnableServicesStep()));
        updateSteps.add(createVariableRegistryUpdateStepDto(request.getStartProcessorsStep()));
        dto.setUpdateSteps(updateSteps);

        dto.setAffectedComponents(new HashSet<>(request.getAffectedComponents().values()));

        return dto;
    }

    public VariableRegistryUpdateStepDTO createVariableRegistryUpdateStepDto(final VariableRegistryUpdateStep step) {
        final VariableRegistryUpdateStepDTO dto = new VariableRegistryUpdateStepDTO();
        dto.setComplete(step.isComplete());
        dto.setDescription(step.getDescription());
        dto.setFailureReason(step.getFailureReason());
        return dto;
    }


    public VariableRegistryDTO populateAffectedComponents(final VariableRegistryDTO variableRegistry, final ProcessGroup group, final RevisionManager revisionManager) {
        if (!group.getIdentifier().equals(variableRegistry.getProcessGroupId())) {
            throw new IllegalArgumentException("Variable Registry does not have the same Group ID as the given Process Group");
        }

        final Set<VariableEntity> variableEntities = new LinkedHashSet<>();

        if (variableRegistry.getVariables() != null) {
            for (final VariableEntity inputEntity : variableRegistry.getVariables()) {
                final VariableEntity entity = new VariableEntity();

                final VariableDTO inputDto = inputEntity.getVariable();
                final VariableDTO variableDto = new VariableDTO();
                variableDto.setName(inputDto.getName());
                variableDto.setValue(inputDto.getValue());
                variableDto.setProcessGroupId(group.getIdentifier());

                final Set<AffectedComponentEntity> affectedComponentEntities = createAffectedComponentEntities(group.getComponentsAffectedByVariable(variableDto.getName()), revisionManager);

                boolean canWrite = true;
                for (final AffectedComponentEntity affectedComponent : affectedComponentEntities) {
                    final PermissionsDTO permissions = affectedComponent.getPermissions();
                    if (!permissions.getCanRead() || !permissions.getCanWrite()) {
                        canWrite = false;
                        break;
                    }
                }

                variableDto.setAffectedComponents(affectedComponentEntities);

                entity.setCanWrite(canWrite);
                entity.setVariable(inputDto);

                variableEntities.add(entity);
            }
        }

        final VariableRegistryDTO registryDto = new VariableRegistryDTO();
        registryDto.setProcessGroupId(group.getIdentifier());
        registryDto.setVariables(variableEntities);

        return registryDto;
    }


    /**
     * Gets the capability description from the specified class.
     */
    private String getCapabilityDescription(final Class<?> cls) {
        final CapabilityDescription capabilityDesc = cls.getAnnotation(CapabilityDescription.class);
        return capabilityDesc == null ? null : capabilityDesc.value();
    }

    /**
     * Gets the tags from the specified class.
     */
    private Set<String> getTags(final Class<?> cls) {
        final Set<String> tags = new HashSet<>();
        final Tags tagsAnnotation = cls.getAnnotation(Tags.class);
        if (tagsAnnotation != null) {
            for (final String tag : tagsAnnotation.value()) {
                tags.add(tag);
            }
        }

        if (cls.isAnnotationPresent(Restricted.class)) {
            tags.add("restricted");
        }

        return tags;
    }

    /**
     * Creates a bundle DTO from the specified class.
     *
     * @param coordinate bundle coordinates
     * @return dto
     */
    public BundleDTO createBundleDto(final BundleCoordinate coordinate) {
        final BundleDTO dto = new BundleDTO();
        dto.setGroup(coordinate.getGroup());
        dto.setArtifact(coordinate.getId());
        dto.setVersion(coordinate.getVersion());
        return dto;
    }

    private List<ControllerServiceApiDTO> createControllerServiceApiDto(final Class cls) {
        final Set<Class> serviceApis = new HashSet<>();

        // if this is a controller service
        if (ControllerService.class.isAssignableFrom(cls)) {
            // get all of it's interfaces to determine the controller service api's it implements
            final List<Class<?>> interfaces = ClassUtils.getAllInterfaces(cls);
            for (final Class i : interfaces) {
                // add all controller services that's not ControllerService itself
                if (ControllerService.class.isAssignableFrom(i) && !ControllerService.class.equals(i)) {
                    serviceApis.add(i);
                }
            }

            final List<ControllerServiceApiDTO> dtos = new ArrayList<>();
            for (final Class serviceApi : serviceApis) {
                final Bundle bundle = extensionManager.getBundle(serviceApi.getClassLoader());
                final BundleCoordinate bundleCoordinate = bundle.getBundleDetails().getCoordinate();

                final ControllerServiceApiDTO dto = new ControllerServiceApiDTO();
                dto.setType(serviceApi.getName());
                dto.setBundle(createBundleDto(bundleCoordinate));
                dtos.add(dto);
            }
            return dtos;
        } else {
            return null;
        }
    }

    /**
     * Gets the DocumentedTypeDTOs from the specified classes.
     *
     * @param classes classes
     * @param bundleGroupFilter if specified, must be member of bundle group
     * @param bundleArtifactFilter if specified, must be member of bundle artifact
     * @param typeFilter if specified, type must match
     * @return dtos
     */
    public Set<DocumentedTypeDTO> fromDocumentedTypes(final Map<Class, Bundle> classes, final String bundleGroupFilter, final String bundleArtifactFilter, final String typeFilter) {
        final Set<DocumentedTypeDTO> types = new LinkedHashSet<>();
        final List<Class> sortedClasses = new ArrayList<>(classes.keySet());
        Collections.sort(sortedClasses, CLASS_NAME_COMPARATOR);

        for (final Class cls : sortedClasses) {
            final Bundle bundle = classes.get(cls);
            final BundleCoordinate coordinate = bundle.getBundleDetails().getCoordinate();

            // only include classes that meet the criteria if specified
            if (bundleGroupFilter != null && !bundleGroupFilter.equals(coordinate.getGroup())) {
                continue;
            }
            if (bundleArtifactFilter != null && !bundleArtifactFilter.equals(coordinate.getId())) {
                continue;
            }
            if (typeFilter != null && !typeFilter.equals(cls.getName())) {
                continue;
            }

            final DocumentedTypeDTO dto = new DocumentedTypeDTO();
            dto.setType(cls.getName());
            dto.setBundle(createBundleDto(coordinate));
            dto.setControllerServiceApis(createControllerServiceApiDto(cls));
            dto.setDescription(getCapabilityDescription(cls));
            dto.setRestricted(isRestricted(cls));
            dto.setUsageRestriction(getUsageRestriction(cls));
            dto.setExplicitRestrictions(getExplicitRestrictions(cls));
            dto.setDeprecationReason(getDeprecationReason(cls));
            dto.setTags(getTags(cls));
            types.add(dto);
        }

        return types;
    }

    /**
     * Gets the DocumentedTypeDTOs from the specified classes.
     *
     * @param extensionDefinitions extensionDefinitions
     * @param bundleGroupFilter if specified, must be member of bundle group
     * @param bundleArtifactFilter if specified, must be member of bundle artifact
     * @param typeFilter if specified, type must match
     * @return dtos
     */
    public Set<DocumentedTypeDTO> fromDocumentedTypes(final Set<ExtensionDefinition> extensionDefinitions, final String bundleGroupFilter, final String bundleArtifactFilter, final String typeFilter) {
        final Map<Class, Bundle> classBundles = new HashMap<>();
        for (final ExtensionDefinition extensionDefinition : extensionDefinitions) {
            final Class cls = extensionManager.getClass(extensionDefinition);
            classBundles.put(cls, extensionDefinition.getBundle());
        }
        return fromDocumentedTypes(classBundles, bundleGroupFilter, bundleArtifactFilter, typeFilter);
    }

    /**
     * Creates a ProcessorDTO from the specified ProcessorNode.
     * @param node node
     * @return dto
     */
    public ProcessorDTO createProcessorDto(final ProcessorNode node) {
        if (node == null) {
            return null;
        }

        final BundleCoordinate bundleCoordinate = node.getBundleCoordinate();
        final List<Bundle> compatibleBundles = extensionManager.getBundles(node.getCanonicalClassName()).stream().filter(bundle -> {
            final BundleCoordinate coordinate = bundle.getBundleDetails().getCoordinate();
            return bundleCoordinate.getGroup().equals(coordinate.getGroup()) && bundleCoordinate.getId().equals(coordinate.getId());
        }).collect(Collectors.toList());

        final ProcessorDTO dto = new ProcessorDTO();
        dto.setId(node.getIdentifier());
        dto.setPosition(createPositionDto(node.getPosition()));
        dto.setStyle(node.getStyle());
        dto.setParentGroupId(node.getProcessGroup().getIdentifier());
        dto.setInputRequirement(node.getInputRequirement().name());
        dto.setPersistsState(node.getProcessor().getClass().isAnnotationPresent(Stateful.class));
        dto.setRestricted(node.isRestricted());
        dto.setDeprecated(node.isDeprecated());
        dto.setExecutionNodeRestricted(node.isExecutionNodeRestricted());
        dto.setExtensionMissing(node.isExtensionMissing());
        dto.setMultipleVersionsAvailable(compatibleBundles.size() > 1);
        dto.setVersionedComponentId(node.getVersionedComponentId().orElse(null));

        dto.setType(node.getCanonicalClassName());
        dto.setBundle(createBundleDto(bundleCoordinate));
        dto.setName(node.getName());
        dto.setState(node.getScheduledState().toString());

        // build the relationship dtos
        final List<RelationshipDTO> relationships = new ArrayList<>();
        for (final Relationship rel : node.getRelationships()) {
            final RelationshipDTO relationshipDTO = new RelationshipDTO();
            relationshipDTO.setDescription(rel.getDescription());
            relationshipDTO.setName(rel.getName());
            relationshipDTO.setAutoTerminate(node.isAutoTerminated(rel));
            relationships.add(relationshipDTO);
        }

        // sort the relationships
        relationships.sort(new Comparator<RelationshipDTO>() {
            @Override
            public int compare(final RelationshipDTO r1, final RelationshipDTO r2) {
                return Collator.getInstance(Locale.US).compare(r1.getName(), r2.getName());
            }
        });

        // set the relationships
        dto.setRelationships(relationships);

        dto.setDescription(getCapabilityDescription(node.getClass()));
        dto.setSupportsParallelProcessing(!node.isTriggeredSerially());
        dto.setSupportsEventDriven(node.isEventDrivenSupported());
        dto.setSupportsBatching(node.isSessionBatchingSupported());

        dto.setConfig(createProcessorConfigDto(node));

        final ValidationStatus validationStatus = node.getValidationStatus();
        dto.setValidationStatus(validationStatus.name());

        final Collection<ValidationResult> validationErrors = node.getValidationErrors();
        if (validationErrors != null && !validationErrors.isEmpty()) {
            final List<String> errors = new ArrayList<>();
            for (final ValidationResult validationResult : validationErrors) {
                errors.add(validationResult.toString());
            }

            dto.setValidationErrors(errors);
        }

        return dto;
    }

    /**
     * Creates a BulletinBoardDTO for the specified bulletins.
     *
     * @param bulletins bulletins
     * @return dto
     */
    public BulletinBoardDTO createBulletinBoardDto(final List<BulletinEntity> bulletins) {
        // sort the bulletins
        Collections.sort(bulletins, new Comparator<BulletinEntity>() {
            @Override
            public int compare(final BulletinEntity bulletin1, final BulletinEntity bulletin2) {
                if (bulletin1 == null && bulletin2 == null) {
                    return 0;
                } else if (bulletin1 == null) {
                    return 1;
                } else if (bulletin2 == null) {
                    return -1;
                }

                final Date timestamp1 = bulletin1.getTimestamp();
                final Date timestamp2 = bulletin2.getTimestamp();
                if (timestamp1 == null && timestamp2 == null) {
                    return 0;
                } else if (timestamp1 == null) {
                    return 1;
                } else if (timestamp2 == null) {
                    return -1;
                } else {
                    return timestamp1.compareTo(timestamp2);
                }
            }
        });

        // create the bulletin board
        final BulletinBoardDTO bulletinBoard = new BulletinBoardDTO();
        bulletinBoard.setBulletins(bulletins);
        bulletinBoard.setGenerated(new Date());
        return bulletinBoard;
    }

    /**
     * Creates BulletinDTOs for the specified Bulletins.
     *
     * @param bulletins bulletin
     * @return dto
     */
    public List<BulletinDTO> createBulletinDtos(final List<Bulletin> bulletins) {
        final List<BulletinDTO> bulletinDtos = new ArrayList<>(bulletins.size());
        for (final Bulletin bulletin : bulletins) {
            bulletinDtos.add(createBulletinDto(bulletin));
        }
        return bulletinDtos;
    }

    /**
     * Creates a BulletinDTO for the specified Bulletin.
     *
     * @param bulletin bulletin
     * @return dto
     */
    public BulletinDTO createBulletinDto(final Bulletin bulletin) {
        final BulletinDTO dto = new BulletinDTO();
        dto.setId(bulletin.getId());
        dto.setNodeAddress(bulletin.getNodeAddress());
        dto.setTimestamp(bulletin.getTimestamp());
        dto.setGroupId(bulletin.getGroupId());
        dto.setSourceId(bulletin.getSourceId());
        dto.setSourceName(bulletin.getSourceName());
        dto.setCategory(bulletin.getCategory());
        dto.setLevel(bulletin.getLevel());
        dto.setMessage(bulletin.getMessage());
        return dto;
    }

    /**
     * Creates a ProvenanceEventNodeDTO for the specified ProvenanceEventLineageNode.
     *
     * @param node node
     * @return dto
     */
    public ProvenanceNodeDTO createProvenanceEventNodeDTO(final ProvenanceEventLineageNode node) {
        final ProvenanceNodeDTO dto = new ProvenanceNodeDTO();
        dto.setId(node.getIdentifier());
        dto.setType("EVENT");
        dto.setEventType(node.getEventType().toString());
        dto.setTimestamp(new Date(node.getTimestamp()));
        dto.setMillis(node.getTimestamp());
        dto.setFlowFileUuid(node.getFlowFileUuid());
        dto.setParentUuids(node.getParentUuids());
        dto.setChildUuids(node.getChildUuids());
        return dto;
    }

    /**
     * Creates a FlowFileNodeDTO for the specified LineageNode.
     *
     * @param node node
     * @return dto
     */
    public ProvenanceNodeDTO createFlowFileNodeDTO(final LineageNode node) {
        final ProvenanceNodeDTO dto = new ProvenanceNodeDTO();
        dto.setId(node.getIdentifier());
        dto.setType("FLOWFILE");
        dto.setTimestamp(new Date(node.getTimestamp()));
        dto.setMillis(node.getTimestamp());
        dto.setFlowFileUuid(node.getFlowFileUuid());
        return dto;
    }

    /**
     * Creates a ProvenanceLinkDTO for the specified LineageEdge.
     *
     * @param edge edge
     * @return dto
     */
    public ProvenanceLinkDTO createProvenanceLinkDTO(final LineageEdge edge) {
        final LineageNode source = edge.getSource();
        final LineageNode target = edge.getDestination();

        final ProvenanceLinkDTO dto = new ProvenanceLinkDTO();
        dto.setTimestamp(new Date(target.getTimestamp()));
        dto.setMillis(target.getTimestamp());
        dto.setFlowFileUuid(edge.getUuid());
        dto.setSourceId(source.getIdentifier());
        dto.setTargetId(target.getIdentifier());
        return dto;
    }

    /**
     * Creates a LineageDTO for the specified Lineage.
     *
     * @param computeLineageSubmission submission
     * @return dto
     */
    public LineageDTO createLineageDto(final ComputeLineageSubmission computeLineageSubmission) {
        // build the lineage dto
        final LineageDTO dto = new LineageDTO();
        final LineageRequestDTO requestDto = new LineageRequestDTO();
        final LineageResultsDTO resultsDto = new LineageResultsDTO();

        // include the original request and results
        dto.setRequest(requestDto);
        dto.setResults(resultsDto);

        // rebuild the request from the submission object
        switch (computeLineageSubmission.getLineageComputationType()) {
            case EXPAND_CHILDREN:
                requestDto.setEventId(computeLineageSubmission.getExpandedEventId());
                requestDto.setLineageRequestType(LineageRequestType.CHILDREN);
                break;
            case EXPAND_PARENTS:
                requestDto.setEventId(computeLineageSubmission.getExpandedEventId());
                requestDto.setLineageRequestType(LineageRequestType.PARENTS);
                break;
            case FLOWFILE_LINEAGE:
                final Collection<String> uuids = computeLineageSubmission.getLineageFlowFileUuids();
                if (uuids.size() == 1) {
                    requestDto.setUuid(uuids.iterator().next());
                }
                requestDto.setEventId(computeLineageSubmission.getExpandedEventId());
                requestDto.setLineageRequestType(LineageRequestType.FLOWFILE);
                break;
        }

        // include lineage details
        dto.setId(computeLineageSubmission.getLineageIdentifier());
        dto.setSubmissionTime(computeLineageSubmission.getSubmissionTime());

        // create the results dto
        final ComputeLineageResult results = computeLineageSubmission.getResult();
        dto.setFinished(results.isFinished());
        dto.setPercentCompleted(results.getPercentComplete());
        dto.setExpiration(results.getExpiration());

        final List<LineageNode> nodes = results.getNodes();
        final List<LineageEdge> edges = results.getEdges();

        final List<ProvenanceNodeDTO> nodeDtos = new ArrayList<>();
        if (results.isFinished()) {
            // create the node dto's
            for (final LineageNode node : nodes) {
                switch (node.getNodeType()) {
                    case FLOWFILE_NODE:
                        nodeDtos.add(createFlowFileNodeDTO(node));
                        break;
                    case PROVENANCE_EVENT_NODE:
                        nodeDtos.add(createProvenanceEventNodeDTO((ProvenanceEventLineageNode) node));
                        break;
                }
            }
        }
        resultsDto.setNodes(nodeDtos);

        // include any errors
        if (results.getError() != null) {
            final Set<String> errors = new HashSet<>();
            errors.add(results.getError());
            resultsDto.setErrors(errors);
        }

        // create the link dto's
        final List<ProvenanceLinkDTO> linkDtos = new ArrayList<>();
        for (final LineageEdge edge : edges) {
            linkDtos.add(createProvenanceLinkDTO(edge));
        }
        resultsDto.setLinks(linkDtos);

        return dto;
    }

    /**
     * Creates a SystemDiagnosticsDTO for the specified SystemDiagnostics.
     *
     * @param sysDiagnostics diags
     * @return dto
     */
    public SystemDiagnosticsDTO createSystemDiagnosticsDto(final SystemDiagnostics sysDiagnostics) {

        final SystemDiagnosticsDTO dto = new SystemDiagnosticsDTO();
        final SystemDiagnosticsSnapshotDTO snapshot = new SystemDiagnosticsSnapshotDTO();
        dto.setAggregateSnapshot(snapshot);

        snapshot.setStatsLastRefreshed(new Date(sysDiagnostics.getCreationTimestamp()));

        // processors
        snapshot.setAvailableProcessors(sysDiagnostics.getAvailableProcessors());
        snapshot.setProcessorLoadAverage(sysDiagnostics.getProcessorLoadAverage());

        // threads
        snapshot.setDaemonThreads(sysDiagnostics.getDaemonThreads());
        snapshot.setTotalThreads(sysDiagnostics.getTotalThreads());

        // heap
        snapshot.setMaxHeap(FormatUtils.formatDataSize(sysDiagnostics.getMaxHeap()));
        snapshot.setMaxHeapBytes(sysDiagnostics.getMaxHeap());
        snapshot.setTotalHeap(FormatUtils.formatDataSize(sysDiagnostics.getTotalHeap()));
        snapshot.setTotalHeapBytes(sysDiagnostics.getTotalHeap());
        snapshot.setUsedHeap(FormatUtils.formatDataSize(sysDiagnostics.getUsedHeap()));
        snapshot.setUsedHeapBytes(sysDiagnostics.getUsedHeap());
        snapshot.setFreeHeap(FormatUtils.formatDataSize(sysDiagnostics.getFreeHeap()));
        snapshot.setFreeHeapBytes(sysDiagnostics.getFreeHeap());
        if (sysDiagnostics.getHeapUtilization() != -1) {
            snapshot.setHeapUtilization(FormatUtils.formatUtilization(sysDiagnostics.getHeapUtilization()));
        }

        // non heap
        snapshot.setMaxNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getMaxNonHeap()));
        snapshot.setMaxNonHeapBytes(sysDiagnostics.getMaxNonHeap());
        snapshot.setTotalNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getTotalNonHeap()));
        snapshot.setTotalNonHeapBytes(sysDiagnostics.getTotalNonHeap());
        snapshot.setUsedNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getUsedNonHeap()));
        snapshot.setUsedNonHeapBytes(sysDiagnostics.getUsedNonHeap());
        snapshot.setFreeNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getFreeNonHeap()));
        snapshot.setFreeNonHeapBytes(sysDiagnostics.getFreeNonHeap());
        if (sysDiagnostics.getNonHeapUtilization() != -1) {
            snapshot.setNonHeapUtilization(FormatUtils.formatUtilization(sysDiagnostics.getNonHeapUtilization()));
        }

        // flow file disk usage
        final SystemDiagnosticsSnapshotDTO.StorageUsageDTO flowFileRepositoryStorageUsageDto = createStorageUsageDTO(null, sysDiagnostics.getFlowFileRepositoryStorageUsage());
        snapshot.setFlowFileRepositoryStorageUsage(flowFileRepositoryStorageUsageDto);

        // content disk usage
        final Set<SystemDiagnosticsSnapshotDTO.StorageUsageDTO> contentRepositoryStorageUsageDtos = new LinkedHashSet<>();
        snapshot.setContentRepositoryStorageUsage(contentRepositoryStorageUsageDtos);
        for (final Map.Entry<String, StorageUsage> entry : sysDiagnostics.getContentRepositoryStorageUsage().entrySet()) {
            contentRepositoryStorageUsageDtos.add(createStorageUsageDTO(entry.getKey(), entry.getValue()));
        }

        // provenance disk usage
        final Set<SystemDiagnosticsSnapshotDTO.StorageUsageDTO> provenanceRepositoryStorageUsageDtos = new LinkedHashSet<>();
        snapshot.setProvenanceRepositoryStorageUsage(provenanceRepositoryStorageUsageDtos);
        for (final Map.Entry<String, StorageUsage> entry : sysDiagnostics.getProvenanceRepositoryStorageUsage().entrySet()) {
            provenanceRepositoryStorageUsageDtos.add(createStorageUsageDTO(entry.getKey(), entry.getValue()));
        }

        // garbage collection
        final Set<SystemDiagnosticsSnapshotDTO.GarbageCollectionDTO> garbageCollectionDtos = new LinkedHashSet<>();
        snapshot.setGarbageCollection(garbageCollectionDtos);
        for (final Map.Entry<String, GarbageCollection> entry : sysDiagnostics.getGarbageCollection().entrySet()) {
            garbageCollectionDtos.add(createGarbageCollectionDTO(entry.getKey(), entry.getValue()));
        }

        // version info
        final SystemDiagnosticsSnapshotDTO.VersionInfoDTO versionInfoDto = createVersionInfoDTO();
        snapshot.setVersionInfo(versionInfoDto);

        // uptime
        snapshot.setUptime(FormatUtils.formatHoursMinutesSeconds(sysDiagnostics.getUptime(), TimeUnit.MILLISECONDS));

        return dto;
    }

    /**
     * Creates a StorageUsageDTO from the specified StorageUsage.
     *
     * @param identifier id
     * @param storageUsage usage
     * @return dto
     */
    public SystemDiagnosticsSnapshotDTO.StorageUsageDTO createStorageUsageDTO(final String identifier, final StorageUsage storageUsage) {
        final SystemDiagnosticsSnapshotDTO.StorageUsageDTO dto = new SystemDiagnosticsSnapshotDTO.StorageUsageDTO();
        dto.setIdentifier(identifier);
        dto.setFreeSpace(FormatUtils.formatDataSize(storageUsage.getFreeSpace()));
        dto.setTotalSpace(FormatUtils.formatDataSize(storageUsage.getTotalSpace()));
        dto.setUsedSpace(FormatUtils.formatDataSize(storageUsage.getUsedSpace()));
        dto.setFreeSpaceBytes(storageUsage.getFreeSpace());
        dto.setTotalSpaceBytes(storageUsage.getTotalSpace());
        dto.setUsedSpaceBytes(storageUsage.getUsedSpace());
        dto.setUtilization(FormatUtils.formatUtilization(storageUsage.getDiskUtilization()));
        return dto;
    }

    /**
     * Creates a GarbageCollectionDTO from the specified GarbageCollection.
     *
     * @param name name
     * @param garbageCollection gc
     * @return dto
     */
    public SystemDiagnosticsSnapshotDTO.GarbageCollectionDTO createGarbageCollectionDTO(final String name, final GarbageCollection garbageCollection) {
        final SystemDiagnosticsSnapshotDTO.GarbageCollectionDTO dto = new SystemDiagnosticsSnapshotDTO.GarbageCollectionDTO();
        dto.setName(name);
        dto.setCollectionCount(garbageCollection.getCollectionCount());
        dto.setCollectionTime(FormatUtils.formatHoursMinutesSeconds(garbageCollection.getCollectionTime(), TimeUnit.MILLISECONDS));
        dto.setCollectionMillis(garbageCollection.getCollectionTime());
        return dto;
    }

    public SystemDiagnosticsSnapshotDTO.VersionInfoDTO createVersionInfoDTO() {
        final SystemDiagnosticsSnapshotDTO.VersionInfoDTO dto = new SystemDiagnosticsSnapshotDTO.VersionInfoDTO();
        dto.setJavaVendor(System.getProperty("java.vendor"));
        dto.setJavaVersion(System.getProperty("java.version"));
        dto.setOsName(System.getProperty("os.name"));
        dto.setOsVersion(System.getProperty("os.version"));
        dto.setOsArchitecture(System.getProperty("os.arch"));

        final Bundle frameworkBundle = NarClassLoadersHolder.getInstance().getFrameworkBundle();
        if (frameworkBundle != null) {
            final BundleDetails frameworkDetails = frameworkBundle.getBundleDetails();

            dto.setNiFiVersion(frameworkDetails.getCoordinate().getVersion());

            // Get build info
            dto.setBuildTag(frameworkDetails.getBuildTag());
            dto.setBuildRevision(frameworkDetails.getBuildRevision());
            dto.setBuildBranch(frameworkDetails.getBuildBranch());
            dto.setBuildTimestamp(frameworkDetails.getBuildTimestampDate());
        }

        return dto;
    }

    /**
     * Creates a ResourceDTO from the specified Resource.
     *
     * @param resource resource
     * @return dto
     */
    public ResourceDTO createResourceDto(final Resource resource) {
        final ResourceDTO dto = new ResourceDTO();
        dto.setIdentifier(resource.getIdentifier());
        dto.setName(resource.getName());
        return dto;
    }

    /**
     * Creates a ProcessorDiagnosticsDTO from the given Processor and status information with some additional supporting information
     *
     * @param procNode the processor to create diagnostics for
     * @param procStatus the status of given processor
     * @param bulletinRepo the bulletin repository
     * @param flowController flowController
     * @param serviceEntityFactory function for creating a ControllerServiceEntity from a given ID
     * @return ProcessorDiagnosticsDTO for the given Processor
     */
    public ProcessorDiagnosticsDTO createProcessorDiagnosticsDto(final ProcessorNode procNode, final ProcessorStatus procStatus, final BulletinRepository bulletinRepo,
            final FlowController flowController, final Function<String, ControllerServiceEntity> serviceEntityFactory) {

        final ProcessorDiagnosticsDTO procDiagnostics = new ProcessorDiagnosticsDTO();

        procDiagnostics.setClassLoaderDiagnostics(createClassLoaderDiagnosticsDto(procNode));
        procDiagnostics.setIncomingConnections(procNode.getIncomingConnections().stream()
            .map(this::createConnectionDiagnosticsDto)
            .collect(Collectors.toSet()));
        procDiagnostics.setOutgoingConnections(procNode.getConnections().stream()
            .map(this::createConnectionDiagnosticsDto)
            .collect(Collectors.toSet()));
        procDiagnostics.setJvmDiagnostics(createJvmDiagnosticsDto(flowController));
        procDiagnostics.setProcessor(createProcessorDto(procNode));
        procDiagnostics.setProcessorStatus(createProcessorStatusDto(procStatus));
        procDiagnostics.setThreadDumps(createThreadDumpDtos(procNode));

        final Set<ControllerServiceDiagnosticsDTO> referencedServiceDiagnostics = createReferencedServiceDiagnostics(procNode.getEffectivePropertyValues(),
            flowController.getControllerServiceProvider(), serviceEntityFactory);
        procDiagnostics.setReferencedControllerServices(referencedServiceDiagnostics);

        return procDiagnostics;
    }

    private Set<ControllerServiceDiagnosticsDTO> createReferencedServiceDiagnostics(final Map<PropertyDescriptor, String> properties, final ControllerServiceProvider serviceProvider,
        final Function<String, ControllerServiceEntity> serviceEntityFactory) {

        final Set<ControllerServiceDiagnosticsDTO> referencedServiceDiagnostics = new HashSet<>();
        for (final Map.Entry<PropertyDescriptor, String> entry : properties.entrySet()) {
            final PropertyDescriptor descriptor = entry.getKey();
            if (descriptor.getControllerServiceDefinition() == null) {
                continue;
            }

            final String serviceId = entry.getValue();
            if (serviceId == null) {
                continue;
            }

            final ControllerServiceNode serviceNode = serviceProvider.getControllerServiceNode(serviceId);
            if (serviceNode == null) {
                continue;
            }

            final ControllerServiceDiagnosticsDTO serviceDiagnostics = createControllerServiceDiagnosticsDto(serviceNode, serviceEntityFactory, serviceProvider);
            if (serviceDiagnostics != null) {
                referencedServiceDiagnostics.add(serviceDiagnostics);
            }
        }

        return referencedServiceDiagnostics;
    }

    /**
     * Creates a ControllerServiceDiagnosticsDTO from the given Controller Service with some additional supporting information
     *
     * @param serviceNode the controller service to create diagnostics for
     * @param serviceEntityFactory a function to convert a controller service id to a controller service entity
     * @param serviceProvider the controller service provider
     * @return ControllerServiceDiagnosticsDTO for the given Controller Service
     */
    public ControllerServiceDiagnosticsDTO createControllerServiceDiagnosticsDto(final ControllerServiceNode serviceNode, final Function<String, ControllerServiceEntity> serviceEntityFactory,
            final ControllerServiceProvider serviceProvider) {

        final ControllerServiceDiagnosticsDTO serviceDiagnostics = new ControllerServiceDiagnosticsDTO();
        final ControllerServiceEntity serviceEntity = serviceEntityFactory.apply(serviceNode.getIdentifier());
        serviceDiagnostics.setControllerService(serviceEntity);

        serviceDiagnostics.setClassLoaderDiagnostics(createClassLoaderDiagnosticsDto(serviceNode));
        return serviceDiagnostics;
    }


    private ClassLoaderDiagnosticsDTO createClassLoaderDiagnosticsDto(final ControllerServiceNode serviceNode) {
        ClassLoader componentClassLoader = extensionManager.getInstanceClassLoader(serviceNode.getIdentifier());
        if (componentClassLoader == null) {
            componentClassLoader = serviceNode.getControllerServiceImplementation().getClass().getClassLoader();
        }

        return createClassLoaderDiagnosticsDto(componentClassLoader);
    }


    private ClassLoaderDiagnosticsDTO createClassLoaderDiagnosticsDto(final ProcessorNode procNode) {
        ClassLoader componentClassLoader = extensionManager.getInstanceClassLoader(procNode.getIdentifier());
        if (componentClassLoader == null) {
            componentClassLoader = procNode.getProcessor().getClass().getClassLoader();
        }

        return createClassLoaderDiagnosticsDto(componentClassLoader);
    }

    private ClassLoaderDiagnosticsDTO createClassLoaderDiagnosticsDto(final ClassLoader classLoader) {
        final ClassLoaderDiagnosticsDTO dto = new ClassLoaderDiagnosticsDTO();

        final Bundle bundle = extensionManager.getBundle(classLoader);
        if (bundle != null) {
            dto.setBundle(createBundleDto(bundle.getBundleDetails().getCoordinate()));
        }

        final ClassLoader parentClassLoader = classLoader.getParent();
        if (parentClassLoader != null) {
            dto.setParentClassLoader(createClassLoaderDiagnosticsDto(parentClassLoader));
        }

        return dto;
    }


    private ConnectionDiagnosticsDTO createConnectionDiagnosticsDto(final Connection connection) {
        final ConnectionDiagnosticsDTO dto = new ConnectionDiagnosticsDTO();
        dto.setConnection(createConnectionDto(connection));
        dto.setAggregateSnapshot(createConnectionDiagnosticsSnapshotDto(connection));
        return dto;
    }

    private ConnectionDiagnosticsSnapshotDTO createConnectionDiagnosticsSnapshotDto(final Connection connection) {
        final ConnectionDiagnosticsSnapshotDTO dto = new ConnectionDiagnosticsSnapshotDTO();

        final QueueDiagnostics queueDiagnostics = connection.getFlowFileQueue().getQueueDiagnostics();

        final FlowFileQueue queue = connection.getFlowFileQueue();
        final QueueSize totalSize = queue.size();
        dto.setTotalByteCount(totalSize.getByteCount());
        dto.setTotalFlowFileCount(totalSize.getObjectCount());

        final LocalQueuePartitionDiagnostics localDiagnostics = queueDiagnostics.getLocalQueuePartitionDiagnostics();
        dto.setLocalQueuePartition(createLocalQueuePartitionDto(localDiagnostics));

        final List<RemoteQueuePartitionDiagnostics> remoteDiagnostics = queueDiagnostics.getRemoteQueuePartitionDiagnostics();
        if (remoteDiagnostics != null) {
            final List<RemoteQueuePartitionDTO> remoteDiagnosticsDtos = remoteDiagnostics.stream()
                .map(this::createRemoteQueuePartitionDto)
                .collect(Collectors.toList());

            dto.setRemoteQueuePartitions(remoteDiagnosticsDtos);
        }

        return dto;
    }

    private LocalQueuePartitionDTO createLocalQueuePartitionDto(final LocalQueuePartitionDiagnostics queueDiagnostics) {
        final LocalQueuePartitionDTO dto = new LocalQueuePartitionDTO();

        final QueueSize activeSize = queueDiagnostics.getActiveQueueSize();
        dto.setActiveQueueByteCount(activeSize.getByteCount());
        dto.setActiveQueueFlowFileCount(activeSize.getObjectCount());

        final QueueSize inFlightSize = queueDiagnostics.getUnacknowledgedQueueSize();
        dto.setInFlightByteCount(inFlightSize.getByteCount());
        dto.setInFlightFlowFileCount(inFlightSize.getObjectCount());

        final QueueSize swapSize = queueDiagnostics.getSwapQueueSize();
        dto.setSwapByteCount(swapSize.getByteCount());
        dto.setSwapFlowFileCount(swapSize.getObjectCount());
        dto.setSwapFiles(queueDiagnostics.getSwapFileCount());

        dto.setTotalByteCount(activeSize.getByteCount() + inFlightSize.getByteCount() + swapSize.getByteCount());
        dto.setTotalFlowFileCount(activeSize.getObjectCount() + inFlightSize.getObjectCount() + swapSize.getObjectCount());

        dto.setAllActiveQueueFlowFilesPenalized(queueDiagnostics.isAllActiveFlowFilesPenalized());
        dto.setAnyActiveQueueFlowFilesPenalized(queueDiagnostics.isAnyActiveFlowFilePenalized());

        return dto;
    }

    private RemoteQueuePartitionDTO createRemoteQueuePartitionDto(final RemoteQueuePartitionDiagnostics queueDiagnostics) {
        final RemoteQueuePartitionDTO dto = new RemoteQueuePartitionDTO();

        dto.setNodeIdentifier(queueDiagnostics.getNodeIdentifier());

        final QueueSize activeSize = queueDiagnostics.getActiveQueueSize();
        dto.setActiveQueueByteCount(activeSize.getByteCount());
        dto.setActiveQueueFlowFileCount(activeSize.getObjectCount());

        final QueueSize inFlightSize = queueDiagnostics.getUnacknowledgedQueueSize();
        dto.setInFlightByteCount(inFlightSize.getByteCount());
        dto.setInFlightFlowFileCount(inFlightSize.getObjectCount());

        final QueueSize swapSize = queueDiagnostics.getSwapQueueSize();
        dto.setSwapByteCount(swapSize.getByteCount());
        dto.setSwapFlowFileCount(swapSize.getObjectCount());
        dto.setSwapFiles(queueDiagnostics.getSwapFileCount());

        dto.setTotalByteCount(activeSize.getByteCount() + inFlightSize.getByteCount() + swapSize.getByteCount());
        dto.setTotalFlowFileCount(activeSize.getObjectCount() + inFlightSize.getObjectCount() + swapSize.getObjectCount());

        return dto;
    }

    private JVMDiagnosticsDTO createJvmDiagnosticsDto(final FlowController flowController) {
        final JVMDiagnosticsDTO dto = new JVMDiagnosticsDTO();
        dto.setAggregateSnapshot(createJvmDiagnosticsSnapshotDto(flowController));
        dto.setClustered(flowController.isClustered());
        dto.setConnected(flowController.isConnected());
        return dto;
    }

    private JVMDiagnosticsSnapshotDTO createJvmDiagnosticsSnapshotDto(final FlowController flowController) {
        final JVMDiagnosticsSnapshotDTO dto = new JVMDiagnosticsSnapshotDTO();

        final JVMControllerDiagnosticsSnapshotDTO controllerDiagnosticsDto = new JVMControllerDiagnosticsSnapshotDTO();
        final JVMFlowDiagnosticsSnapshotDTO flowDiagnosticsDto = new JVMFlowDiagnosticsSnapshotDTO();
        final JVMSystemDiagnosticsSnapshotDTO systemDiagnosticsDto = new JVMSystemDiagnosticsSnapshotDTO();

        dto.setControllerDiagnostics(controllerDiagnosticsDto);
        dto.setFlowDiagnosticsDto(flowDiagnosticsDto);
        dto.setSystemDiagnosticsDto(systemDiagnosticsDto);

        final SystemDiagnostics systemDiagnostics = flowController.getSystemDiagnostics();

        // flow-related information
        final Set<BundleDTO> bundlesLoaded = extensionManager.getAllBundles().stream()
            .map(bundle -> bundle.getBundleDetails().getCoordinate())
            .sorted((a, b) -> a.getCoordinate().compareTo(b.getCoordinate()))
            .map(this::createBundleDto)
            .collect(Collectors.toCollection(LinkedHashSet::new));

        flowDiagnosticsDto.setActiveEventDrivenThreads(flowController.getActiveEventDrivenThreadCount());
        flowDiagnosticsDto.setActiveTimerDrivenThreads(flowController.getActiveTimerDrivenThreadCount());
        flowDiagnosticsDto.setBundlesLoaded(bundlesLoaded);
        flowDiagnosticsDto.setTimeZone(System.getProperty("user.timezone"));
        flowDiagnosticsDto.setUptime(FormatUtils.formatHoursMinutesSeconds(systemDiagnostics.getUptime(), TimeUnit.MILLISECONDS));

        // controller-related information
        controllerDiagnosticsDto.setClusterCoordinator(flowController.isClusterCoordinator());
        controllerDiagnosticsDto.setPrimaryNode(flowController.isPrimary());
        controllerDiagnosticsDto.setMaxEventDrivenThreads(flowController.getMaxEventDrivenThreadCount());
        controllerDiagnosticsDto.setMaxTimerDrivenThreads(flowController.getMaxTimerDrivenThreadCount());

        // system-related information
        systemDiagnosticsDto.setMaxOpenFileDescriptors(systemDiagnostics.getMaxOpenFileHandles());
        systemDiagnosticsDto.setOpenFileDescriptors(systemDiagnostics.getOpenFileHandles());
        systemDiagnosticsDto.setPhysicalMemoryBytes(systemDiagnostics.getTotalPhysicalMemory());
        systemDiagnosticsDto.setPhysicalMemory(FormatUtils.formatDataSize(systemDiagnostics.getTotalPhysicalMemory()));

        final NumberFormat percentageFormat = NumberFormat.getPercentInstance();
        percentageFormat.setMaximumFractionDigits(2);

        final Set<RepositoryUsageDTO> contentRepoUsage = new HashSet<>();
        for (final Map.Entry<String, StorageUsage> entry : systemDiagnostics.getContentRepositoryStorageUsage().entrySet()) {
            final String repoName = entry.getKey();
            final StorageUsage usage = entry.getValue();

            final RepositoryUsageDTO usageDto = new RepositoryUsageDTO();
            usageDto.setName(repoName);

            usageDto.setFileStoreHash(DigestUtils.sha256Hex(flowController.getContentRepoFileStoreName(repoName)));
            usageDto.setFreeSpace(FormatUtils.formatDataSize(usage.getFreeSpace()));
            usageDto.setFreeSpaceBytes(usage.getFreeSpace());
            usageDto.setTotalSpace(FormatUtils.formatDataSize(usage.getTotalSpace()));
            usageDto.setTotalSpaceBytes(usage.getTotalSpace());

            final double usedPercentage = (usage.getTotalSpace() - usage.getFreeSpace()) / (double) usage.getTotalSpace();
            final String utilization = percentageFormat.format(usedPercentage);
            usageDto.setUtilization(utilization);
            contentRepoUsage.add(usageDto);
        }

        final Set<RepositoryUsageDTO> provRepoUsage = new HashSet<>();
        for (final Map.Entry<String, StorageUsage> entry : systemDiagnostics.getProvenanceRepositoryStorageUsage().entrySet()) {
            final String repoName = entry.getKey();
            final StorageUsage usage = entry.getValue();

            final RepositoryUsageDTO usageDto = new RepositoryUsageDTO();
            usageDto.setName(repoName);

            usageDto.setFileStoreHash(DigestUtils.sha256Hex(flowController.getProvenanceRepoFileStoreName(repoName)));
            usageDto.setFreeSpace(FormatUtils.formatDataSize(usage.getFreeSpace()));
            usageDto.setFreeSpaceBytes(usage.getFreeSpace());
            usageDto.setTotalSpace(FormatUtils.formatDataSize(usage.getTotalSpace()));
            usageDto.setTotalSpaceBytes(usage.getTotalSpace());

            final double usedPercentage = (usage.getTotalSpace() - usage.getFreeSpace()) / (double) usage.getTotalSpace();
            final String utilization = percentageFormat.format(usedPercentage);
            usageDto.setUtilization(utilization);
            provRepoUsage.add(usageDto);
        }

        final RepositoryUsageDTO flowFileRepoUsage = new RepositoryUsageDTO();
        for (final Map.Entry<String, StorageUsage> entry : systemDiagnostics.getProvenanceRepositoryStorageUsage().entrySet()) {
            final String repoName = entry.getKey();
            final StorageUsage usage = entry.getValue();

            flowFileRepoUsage.setName(repoName);

            flowFileRepoUsage.setFileStoreHash(DigestUtils.sha256Hex(flowController.getFlowRepoFileStoreName()));
            flowFileRepoUsage.setFreeSpace(FormatUtils.formatDataSize(usage.getFreeSpace()));
            flowFileRepoUsage.setFreeSpaceBytes(usage.getFreeSpace());
            flowFileRepoUsage.setTotalSpace(FormatUtils.formatDataSize(usage.getTotalSpace()));
            flowFileRepoUsage.setTotalSpaceBytes(usage.getTotalSpace());

            final double usedPercentage = (usage.getTotalSpace() - usage.getFreeSpace()) / (double) usage.getTotalSpace();
            final String utilization = percentageFormat.format(usedPercentage);
            flowFileRepoUsage.setUtilization(utilization);
        }

        systemDiagnosticsDto.setContentRepositoryStorageUsage(contentRepoUsage);
        systemDiagnosticsDto.setCpuCores(systemDiagnostics.getAvailableProcessors());
        systemDiagnosticsDto.setCpuLoadAverage(systemDiagnostics.getProcessorLoadAverage());
        systemDiagnosticsDto.setFlowFileRepositoryStorageUsage(flowFileRepoUsage);
        systemDiagnosticsDto.setMaxHeapBytes(systemDiagnostics.getMaxHeap());
        systemDiagnosticsDto.setMaxHeap(FormatUtils.formatDataSize(systemDiagnostics.getMaxHeap()));
        systemDiagnosticsDto.setProvenanceRepositoryStorageUsage(provRepoUsage);

        // Create the Garbage Collection History info
        final GarbageCollectionHistory gcHistory = flowController.getGarbageCollectionHistory();
        final List<GarbageCollectionDiagnosticsDTO> gcDiagnostics = new ArrayList<>();
        for (final String memoryManager : gcHistory.getMemoryManagerNames()) {
            final List<GarbageCollectionStatus> statuses = gcHistory.getGarbageCollectionStatuses(memoryManager);

            final List<GCDiagnosticsSnapshotDTO> gcSnapshots = new ArrayList<>();
            for (final GarbageCollectionStatus status : statuses) {
                final GCDiagnosticsSnapshotDTO snapshotDto = new GCDiagnosticsSnapshotDTO();
                snapshotDto.setTimestamp(status.getTimestamp());
                snapshotDto.setCollectionCount(status.getCollectionCount());
                snapshotDto.setCollectionMillis(status.getCollectionMillis());
                gcSnapshots.add(snapshotDto);
            }

            gcSnapshots.sort(Comparator.comparing(GCDiagnosticsSnapshotDTO::getTimestamp).reversed());

            final GarbageCollectionDiagnosticsDTO gcDto = new GarbageCollectionDiagnosticsDTO();
            gcDto.setMemoryManagerName(memoryManager);
            gcDto.setSnapshots(gcSnapshots);
            gcDiagnostics.add(gcDto);
        }

        systemDiagnosticsDto.setGarbageCollectionDiagnostics(gcDiagnostics);

        return dto;
    }

    private List<ThreadDumpDTO> createThreadDumpDtos(final ProcessorNode procNode) {
        final List<ThreadDumpDTO> threadDumps = new ArrayList<>();

        final List<ActiveThreadInfo> activeThreads = procNode.getActiveThreads(ThreadDetails.capture());
        for (final ActiveThreadInfo threadInfo : activeThreads) {
            final ThreadDumpDTO dto = new ThreadDumpDTO();
            dto.setStackTrace(threadInfo.getStackTrace());
            dto.setThreadActiveMillis(threadInfo.getActiveMillis());
            dto.setThreadName(threadInfo.getThreadName());
            dto.setTaskTerminated(threadInfo.isTerminated());
            threadDumps.add(dto);
        }

        return threadDumps;
    }

    /**
     * Creates a ProcessorConfigDTO from the specified ProcessorNode.
     *
     * @param procNode node
     * @return dto
     */
    public ProcessorConfigDTO createProcessorConfigDto(final ProcessorNode procNode) {
        if (procNode == null) {
            return null;
        }

        final ProcessorConfigDTO dto = new ProcessorConfigDTO();

        // sort a copy of the properties
        final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
            @Override
            public int compare(final PropertyDescriptor o1, final PropertyDescriptor o2) {
                return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
            }
        });
        sortedProperties.putAll(procNode.getRawPropertyValues());

        // get the property order from the processor
        final Processor processor = procNode.getProcessor();
        final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
        final List<PropertyDescriptor> descriptors = processor.getPropertyDescriptors();
        if (descriptors != null && !descriptors.isEmpty()) {
            for (final PropertyDescriptor descriptor : descriptors) {
                orderedProperties.put(descriptor, null);
            }
        }
        orderedProperties.putAll(sortedProperties);

        // build the descriptor and property dtos
        dto.setDescriptors(new LinkedHashMap<String, PropertyDescriptorDTO>());
        dto.setProperties(new LinkedHashMap<String, String>());
        for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
            final PropertyDescriptor descriptor = entry.getKey();

            // store the property descriptor
            dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor, procNode.getProcessGroup().getIdentifier()));

            // determine the property value - don't include sensitive properties
            String propertyValue = entry.getValue();
            if (propertyValue != null && descriptor.isSensitive()) {
                propertyValue = SENSITIVE_VALUE_MASK;
            } else if (propertyValue == null && descriptor.getDefaultValue() != null) {
                propertyValue = descriptor.getDefaultValue();
            }

            // set the property value
            dto.getProperties().put(descriptor.getName(), propertyValue);
        }

        dto.setSchedulingPeriod(procNode.getSchedulingPeriod());
        dto.setPenaltyDuration(procNode.getPenalizationPeriod());
        dto.setYieldDuration(procNode.getYieldPeriod());
        dto.setRunDurationMillis(procNode.getRunDuration(TimeUnit.MILLISECONDS));
        dto.setConcurrentlySchedulableTaskCount(procNode.getMaxConcurrentTasks());
        dto.setLossTolerant(procNode.isLossTolerant());
        dto.setComments(procNode.getComments());
        dto.setBulletinLevel(procNode.getBulletinLevel().name());
        dto.setSchedulingStrategy(procNode.getSchedulingStrategy().name());
        dto.setExecutionNode(procNode.getExecutionNode().name());
        dto.setAnnotationData(procNode.getAnnotationData());

        // set up the default values for concurrent tasks and scheduling period
        final Map<String, String> defaultConcurrentTasks = new HashMap<>();
        defaultConcurrentTasks.put(SchedulingStrategy.TIMER_DRIVEN.name(), String.valueOf(SchedulingStrategy.TIMER_DRIVEN.getDefaultConcurrentTasks()));
        defaultConcurrentTasks.put(SchedulingStrategy.EVENT_DRIVEN.name(), String.valueOf(SchedulingStrategy.EVENT_DRIVEN.getDefaultConcurrentTasks()));
        defaultConcurrentTasks.put(SchedulingStrategy.CRON_DRIVEN.name(), String.valueOf(SchedulingStrategy.CRON_DRIVEN.getDefaultConcurrentTasks()));
        dto.setDefaultConcurrentTasks(defaultConcurrentTasks);

        final Map<String, String> defaultSchedulingPeriod = new HashMap<>();
        defaultSchedulingPeriod.put(SchedulingStrategy.TIMER_DRIVEN.name(), SchedulingStrategy.TIMER_DRIVEN.getDefaultSchedulingPeriod());
        defaultSchedulingPeriod.put(SchedulingStrategy.CRON_DRIVEN.name(), SchedulingStrategy.CRON_DRIVEN.getDefaultSchedulingPeriod());
        dto.setDefaultSchedulingPeriod(defaultSchedulingPeriod);

        return dto;
    }

    /**
     * Creates a PropertyDesriptorDTO from the specified PropertyDesriptor.
     *
     * @param propertyDescriptor descriptor
     * @param groupId the Identifier of the Process Group that the component belongs to
     * @return dto
     */
    public PropertyDescriptorDTO createPropertyDescriptorDto(final PropertyDescriptor propertyDescriptor, final String groupId) {
        if (propertyDescriptor == null) {
            return null;
        }

        final PropertyDescriptorDTO dto = new PropertyDescriptorDTO();

        dto.setName(propertyDescriptor.getName());
        dto.setDisplayName(propertyDescriptor.getDisplayName());
        dto.setRequired(propertyDescriptor.isRequired());
        dto.setSensitive(propertyDescriptor.isSensitive());
        dto.setDynamic(propertyDescriptor.isDynamic());
        dto.setDescription(propertyDescriptor.getDescription());
        dto.setDefaultValue(propertyDescriptor.getDefaultValue());
        dto.setSupportsEl(propertyDescriptor.isExpressionLanguageSupported());

        // to support legacy/deprecated method .expressionLanguageSupported(true)
        String description = propertyDescriptor.isExpressionLanguageSupported()
                && propertyDescriptor.getExpressionLanguageScope().equals(ExpressionLanguageScope.NONE)
                ? "true (undefined scope)" : propertyDescriptor.getExpressionLanguageScope().getDescription();
        dto.setExpressionLanguageScope(description);

        // set the identifies controller service is applicable
        if (propertyDescriptor.getControllerServiceDefinition() != null) {
            final Class serviceClass = propertyDescriptor.getControllerServiceDefinition();
            final Bundle serviceBundle = extensionManager.getBundle(serviceClass.getClassLoader());

            dto.setIdentifiesControllerService(serviceClass.getName());
            dto.setIdentifiesControllerServiceBundle(createBundleDto(serviceBundle.getBundleDetails().getCoordinate()));
        }

        final Class<? extends ControllerService> serviceDefinition = propertyDescriptor.getControllerServiceDefinition();
        if (propertyDescriptor.getAllowableValues() == null) {
            if (serviceDefinition == null) {
                dto.setAllowableValues(null);
            } else {
                final List<AllowableValueEntity> allowableValues = new ArrayList<>();
                final List<String> controllerServiceIdentifiers = new ArrayList<>(controllerServiceProvider.getControllerServiceIdentifiers(serviceDefinition, groupId));
                Collections.sort(controllerServiceIdentifiers, Collator.getInstance(Locale.US));
                for (final String serviceIdentifier : controllerServiceIdentifiers) {
                    final ControllerServiceNode service = controllerServiceProvider.getControllerServiceNode(serviceIdentifier);
                    final boolean isServiceAuthorized = service.isAuthorized(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
                    final String displayName = isServiceAuthorized ? service.getName() : serviceIdentifier;

                    final AllowableValueDTO allowableValue = new AllowableValueDTO();
                    allowableValue.setDisplayName(displayName);
                    allowableValue.setValue(serviceIdentifier);
                    allowableValues.add(entityFactory.createAllowableValueEntity(allowableValue, isServiceAuthorized));
                }
                dto.setAllowableValues(allowableValues);
            }
        } else {
            final List<AllowableValueEntity> allowableValues = new ArrayList<>();
            for (final AllowableValue allowableValue : propertyDescriptor.getAllowableValues()) {
                final AllowableValueDTO allowableValueDto = new AllowableValueDTO();
                allowableValueDto.setDisplayName(allowableValue.getDisplayName());
                allowableValueDto.setValue(allowableValue.getValue());
                allowableValueDto.setDescription(allowableValue.getDescription());
                allowableValues.add(entityFactory.createAllowableValueEntity(allowableValueDto, true));
            }

            dto.setAllowableValues(allowableValues);
        }

        // Add any dependencies
        final Set<PropertyDependency> dependencies = propertyDescriptor.getDependencies();
        final List<PropertyDependencyDTO> dependencyDtos = dependencies.stream()
            .map(this::createPropertyDependencyDto)
            .collect(Collectors.toList());
        dto.setDependencies(dependencyDtos);

        return dto;
    }

    private PropertyDependencyDTO createPropertyDependencyDto(final PropertyDependency dependency) {
        final PropertyDependencyDTO dto = new PropertyDependencyDTO();
        dto.setPropertyName(dependency.getPropertyName());
        dto.setDependentValues(dependency.getDependentValues());
        return dto;
    }

    // Copy methods
    public LabelDTO copy(final LabelDTO original) {
        final LabelDTO copy = new LabelDTO();
        copy.setId(original.getId());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setLabel(original.getLabel());
        copy.setStyle(copy(original.getStyle()));
        copy.setPosition(original.getPosition());
        copy.setWidth(original.getWidth());
        copy.setHeight(original.getHeight());
        copy.setVersionedComponentId(original.getVersionedComponentId());

        return copy;
    }

    public ControllerServiceDTO copy(final ControllerServiceDTO original) {
        final ControllerServiceDTO copy = new ControllerServiceDTO();
        copy.setAnnotationData(original.getAnnotationData());
        copy.setControllerServiceApis(original.getControllerServiceApis());
        copy.setComments(original.getComments());
        copy.setCustomUiUrl(original.getCustomUiUrl());
        copy.setDescriptors(copy(original.getDescriptors()));
        copy.setId(original.getId());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setName(original.getName());
        copy.setProperties(copy(original.getProperties()));
        copy.setReferencingComponents(copy(original.getReferencingComponents()));
        copy.setState(original.getState());
        copy.setType(original.getType());
        copy.setBundle(copy(original.getBundle()));
        copy.setExtensionMissing(original.getExtensionMissing());
        copy.setMultipleVersionsAvailable(original.getMultipleVersionsAvailable());
        copy.setPersistsState(original.getPersistsState());
        copy.setValidationErrors(copy(original.getValidationErrors()));
        copy.setValidationStatus(original.getValidationStatus());
        copy.setVersionedComponentId(original.getVersionedComponentId());
        return copy;
    }

    public FunnelDTO copy(final FunnelDTO original) {
        final FunnelDTO copy = new FunnelDTO();
        copy.setId(original.getId());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setPosition(original.getPosition());
        copy.setVersionedComponentId(original.getVersionedComponentId());

        return copy;
    }

    private <T> List<T> copy(final List<T> original) {
        if (original == null) {
            return null;
        } else {
            return new ArrayList<>(original);
        }
    }

    private <T> List<T> copy(final Collection<T> original) {
        if (original == null) {
            return null;
        } else {
            return new ArrayList<>(original);
        }
    }

    private <T> Set<T> copy(final Set<T> original) {
        if (original == null) {
            return null;
        } else {
            return new LinkedHashSet<>(original);
        }
    }

    private <S, T> Map<S, T> copy(final Map<S, T> original) {
        if (original == null) {
            return null;
        } else {
            return new LinkedHashMap<>(original);
        }
    }

    public BundleDTO copy(final BundleDTO original) {
        if (original == null) {
            return null;
        }

        final BundleDTO copy = new BundleDTO();
        copy.setGroup(original.getGroup());
        copy.setArtifact(original.getArtifact());
        copy.setVersion(original.getVersion());
        return copy;
    }

    public ProcessorDTO copy(final ProcessorDTO original) {
        final ProcessorDTO copy = new ProcessorDTO();
        copy.setConfig(copy(original.getConfig()));
        copy.setPosition(original.getPosition());
        copy.setId(original.getId());
        copy.setName(original.getName());
        copy.setDescription(original.getDescription());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setRelationships(copy(original.getRelationships()));
        copy.setState(original.getState());
        copy.setStyle(copy(original.getStyle()));
        copy.setType(original.getType());
        copy.setBundle(copy(original.getBundle()));
        copy.setSupportsParallelProcessing(original.getSupportsParallelProcessing());
        copy.setSupportsEventDriven(original.getSupportsEventDriven());
        copy.setSupportsBatching(original.getSupportsBatching());
        copy.setPersistsState(original.getPersistsState());
        copy.setExecutionNodeRestricted(original.isExecutionNodeRestricted());
        copy.setExtensionMissing(original.getExtensionMissing());
        copy.setMultipleVersionsAvailable(original.getMultipleVersionsAvailable());
        copy.setValidationErrors(copy(original.getValidationErrors()));
        copy.setValidationStatus(original.getValidationStatus());
        copy.setVersionedComponentId(original.getVersionedComponentId());

        return copy;
    }

    private ProcessorConfigDTO copy(final ProcessorConfigDTO original) {
        final ProcessorConfigDTO copy = new ProcessorConfigDTO();
        copy.setAnnotationData(original.getAnnotationData());
        copy.setAutoTerminatedRelationships(copy(original.getAutoTerminatedRelationships()));
        copy.setComments(original.getComments());
        copy.setSchedulingStrategy(original.getSchedulingStrategy());
        copy.setExecutionNode(original.getExecutionNode());
        copy.setConcurrentlySchedulableTaskCount(original.getConcurrentlySchedulableTaskCount());
        copy.setCustomUiUrl(original.getCustomUiUrl());
        copy.setDescriptors(copy(original.getDescriptors()));
        copy.setProperties(copy(original.getProperties()));
        copy.setSchedulingPeriod(original.getSchedulingPeriod());
        copy.setPenaltyDuration(original.getPenaltyDuration());
        copy.setYieldDuration(original.getYieldDuration());
        copy.setRunDurationMillis(original.getRunDurationMillis());
        copy.setBulletinLevel(original.getBulletinLevel());
        copy.setDefaultConcurrentTasks(original.getDefaultConcurrentTasks());
        copy.setDefaultSchedulingPeriod(original.getDefaultSchedulingPeriod());
        copy.setLossTolerant(original.isLossTolerant());

        return copy;
    }

    public ConnectionDTO copy(final ConnectionDTO original) {
        final ConnectionDTO copy = new ConnectionDTO();
        copy.setAvailableRelationships(copy(original.getAvailableRelationships()));
        copy.setDestination(original.getDestination());
        copy.setPosition(original.getPosition());
        copy.setId(original.getId());
        copy.setName(original.getName());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setSelectedRelationships(copy(original.getSelectedRelationships()));
        copy.setFlowFileExpiration(original.getFlowFileExpiration());
        copy.setBackPressureObjectThreshold(original.getBackPressureObjectThreshold());
        copy.setBackPressureDataSizeThreshold(original.getBackPressureDataSizeThreshold());
        copy.setPrioritizers(copy(original.getPrioritizers()));
        copy.setSource(original.getSource());
        copy.setzIndex(original.getzIndex());
        copy.setLabelIndex(original.getLabelIndex());
        copy.setBends(copy(original.getBends()));
        copy.setLoadBalancePartitionAttribute(original.getLoadBalancePartitionAttribute());
        copy.setLoadBalanceStrategy(original.getLoadBalanceStrategy());
        copy.setLoadBalanceCompression(original.getLoadBalanceCompression());
        copy.setLoadBalanceStatus(original.getLoadBalanceStatus());
        copy.setVersionedComponentId(original.getVersionedComponentId());

        return copy;
    }

    public BulletinDTO copy(final BulletinDTO original) {
        final BulletinDTO copy = new BulletinDTO();
        copy.setId(original.getId());
        copy.setTimestamp(original.getTimestamp());
        copy.setGroupId(original.getGroupId());
        copy.setSourceId(original.getSourceId());
        copy.setSourceName(original.getSourceName());
        copy.setCategory(original.getCategory());
        copy.setLevel(original.getLevel());
        copy.setMessage(original.getMessage());
        copy.setNodeAddress(original.getNodeAddress());
        return copy;
    }

    public PortDTO copy(final PortDTO original) {
        final PortDTO copy = new PortDTO();
        copy.setPosition(original.getPosition());
        copy.setId(original.getId());
        copy.setName(original.getName());
        copy.setComments(original.getComments());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setState(original.getState());
        copy.setType(original.getType());
        copy.setTransmitting(original.isTransmitting());
        copy.setConcurrentlySchedulableTaskCount(original.getConcurrentlySchedulableTaskCount());
        copy.setUserAccessControl(copy(original.getUserAccessControl()));
        copy.setGroupAccessControl(copy(original.getGroupAccessControl()));
        copy.setValidationErrors(copy(original.getValidationErrors()));
        copy.setVersionedComponentId(original.getVersionedComponentId());
        copy.setAllowRemoteAccess(original.getAllowRemoteAccess());
        return copy;
    }

    public RemoteProcessGroupPortDTO copy(final RemoteProcessGroupPortDTO original) {
        final RemoteProcessGroupPortDTO copy = new RemoteProcessGroupPortDTO();
        copy.setId(original.getId());
        copy.setTargetId(original.getTargetId());
        copy.setGroupId(original.getGroupId());
        copy.setName(original.getName());
        copy.setComments(original.getComments());
        copy.setConnected(original.isConnected());
        copy.setTargetRunning(original.isTargetRunning());
        copy.setTransmitting(original.isTransmitting());
        copy.setConcurrentlySchedulableTaskCount(original.getConcurrentlySchedulableTaskCount());
        copy.setUseCompression(original.getUseCompression());
        copy.setExists(original.getExists());
        copy.setVersionedComponentId(original.getVersionedComponentId());

        final BatchSettingsDTO batchOrg = original.getBatchSettings();
        if (batchOrg != null) {
            final BatchSettingsDTO batchCopy = new BatchSettingsDTO();
            batchCopy.setCount(batchOrg.getCount());
            batchCopy.setSize(batchOrg.getSize());
            batchCopy.setDuration(batchOrg.getDuration());
            copy.setBatchSettings(batchCopy);
        }
        return copy;
    }

    public ProcessGroupDTO copy(final ProcessGroupDTO original, final boolean deep) {
        final ProcessGroupDTO copy = new ProcessGroupDTO();
        copy.setComments(original.getComments());
        copy.setContents(copy(original.getContents(), deep));
        copy.setPosition(original.getPosition());
        copy.setId(original.getId());
        copy.setLocalInputPortCount(original.getLocalInputPortCount());
        copy.setPublicInputPortCount(original.getPublicInputPortCount());
        copy.setInvalidCount(original.getInvalidCount());
        copy.setName(original.getName());
        copy.setVersionControlInformation(copy(original.getVersionControlInformation()));
        copy.setParameterContext(copy(original.getParameterContext()));
        copy.setLocalOutputPortCount(original.getLocalOutputPortCount());
        copy.setPublicOutputPortCount(original.getPublicOutputPortCount());
        copy.setOutputPortCount(original.getOutputPortCount());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setVersionedComponentId(original.getVersionedComponentId());
        copy.setFlowfileConcurrency(original.getFlowfileConcurrency());
        copy.setFlowfileOutboundPolicy(original.getFlowfileOutboundPolicy());

        copy.setRunningCount(original.getRunningCount());
        copy.setStoppedCount(original.getStoppedCount());
        copy.setDisabledCount(original.getDisabledCount());
        copy.setActiveRemotePortCount(original.getActiveRemotePortCount());
        copy.setInactiveRemotePortCount(original.getInactiveRemotePortCount());

        copy.setUpToDateCount(original.getUpToDateCount());
        copy.setLocallyModifiedCount(original.getLocallyModifiedCount());
        copy.setStaleCount(original.getStaleCount());
        copy.setLocallyModifiedAndStaleCount(original.getLocallyModifiedAndStaleCount());
        copy.setSyncFailureCount(original.getSyncFailureCount());

        if (original.getVariables() != null) {
            copy.setVariables(new HashMap<>(original.getVariables()));
        }

        return copy;
    }

    public ParameterContextReferenceEntity copy(final ParameterContextReferenceEntity original) {
        if (original == null) {
            return null;
        }

        final ParameterContextReferenceEntity copy = new ParameterContextReferenceEntity();
        copy.setId(original.getId());
        copy.setPermissions(copy(original.getPermissions()));

        if (original.getComponent() != null) {
            final ParameterContextReferenceDTO dtoOriginal = original.getComponent();

            final ParameterContextReferenceDTO dtoCopy = new ParameterContextReferenceDTO();
            dtoCopy.setId(dtoOriginal.getId());
            dtoCopy.setName(dtoOriginal.getName());
            copy.setComponent(dtoCopy);
        }

        return copy;
    }

    public PermissionsDTO copy(final PermissionsDTO original) {
        if (original == null) {
            return null;
        }

        final PermissionsDTO copy = new PermissionsDTO();
        copy.setCanRead(original.getCanRead());
        copy.setCanWrite(original.getCanWrite());
        return copy;
    }

    public VersionControlInformationDTO copy(final VersionControlInformationDTO original) {
        if (original == null) {
            return null;
        }

        final VersionControlInformationDTO copy = new VersionControlInformationDTO();
        copy.setRegistryId(original.getRegistryId());
        copy.setRegistryName(original.getRegistryName());
        copy.setBucketId(original.getBucketId());
        copy.setBucketName(original.getBucketName());
        copy.setFlowId(original.getFlowId());
        copy.setFlowName(original.getFlowName());
        copy.setFlowDescription(original.getFlowDescription());
        copy.setVersion(original.getVersion());
        copy.setState(original.getState());
        copy.setStateExplanation(original.getStateExplanation());
        return copy;
    }

    public RemoteProcessGroupDTO copy(final RemoteProcessGroupDTO original) {
        final RemoteProcessGroupContentsDTO originalContents = original.getContents();
        final RemoteProcessGroupContentsDTO copyContents = new RemoteProcessGroupContentsDTO();

        if (originalContents.getInputPorts() != null) {
            final Set<RemoteProcessGroupPortDTO> inputPorts = new HashSet<>();
            for (final RemoteProcessGroupPortDTO port : originalContents.getInputPorts()) {
                inputPorts.add(copy(port));
            }
            copyContents.setInputPorts(inputPorts);
        }

        if (originalContents.getOutputPorts() != null) {
            final Set<RemoteProcessGroupPortDTO> outputPorts = new HashSet<>();
            for (final RemoteProcessGroupPortDTO port : originalContents.getOutputPorts()) {
                outputPorts.add(copy(port));
            }
            copyContents.setOutputPorts(outputPorts);
        }

        final RemoteProcessGroupDTO copy = new RemoteProcessGroupDTO();
        copy.setComments(original.getComments());
        copy.setPosition(original.getPosition());
        copy.setId(original.getId());
        copy.setCommunicationsTimeout(original.getCommunicationsTimeout());
        copy.setYieldDuration(original.getYieldDuration());
        copy.setName(original.getName());
        copy.setInputPortCount(original.getInputPortCount());
        copy.setOutputPortCount(original.getOutputPortCount());
        copy.setActiveRemoteInputPortCount(original.getActiveRemoteInputPortCount());
        copy.setInactiveRemoteInputPortCount(original.getInactiveRemoteInputPortCount());
        copy.setActiveRemoteOutputPortCount(original.getActiveRemoteOutputPortCount());
        copy.setInactiveRemoteOutputPortCount(original.getInactiveRemoteOutputPortCount());
        copy.setParentGroupId(original.getParentGroupId());
        copy.setTargetUris(original.getTargetUris());
        copy.setTransportProtocol(original.getTransportProtocol());
        copy.setProxyHost(original.getProxyHost());
        copy.setProxyPort(original.getProxyPort());
        copy.setProxyUser(original.getProxyUser());
        copy.setProxyPassword(original.getProxyPassword());
        copy.setLocalNetworkInterface(original.getLocalNetworkInterface());
        copy.setVersionedComponentId(original.getVersionedComponentId());

        copy.setContents(copyContents);

        return copy;
    }

    public ConnectableDTO createConnectableDto(final PortDTO port, final ConnectableType type) {
        final ConnectableDTO connectable = new ConnectableDTO();
        connectable.setGroupId(port.getParentGroupId());
        connectable.setId(port.getId());
        connectable.setName(port.getName());
        connectable.setType(type.name());
        connectable.setVersionedComponentId(port.getVersionedComponentId());
        return connectable;
    }

    public ConnectableDTO createConnectableDto(final ProcessorDTO processor) {
        final ConnectableDTO connectable = new ConnectableDTO();
        connectable.setGroupId(processor.getParentGroupId());
        connectable.setId(processor.getId());
        connectable.setName(processor.getName());
        connectable.setType(ConnectableType.PROCESSOR.name());
        connectable.setVersionedComponentId(processor.getVersionedComponentId());
        return connectable;
    }

    public ConnectableDTO createConnectableDto(final FunnelDTO funnel) {
        final ConnectableDTO connectable = new ConnectableDTO();
        connectable.setGroupId(funnel.getParentGroupId());
        connectable.setId(funnel.getId());
        connectable.setType(ConnectableType.FUNNEL.name());
        connectable.setVersionedComponentId(funnel.getVersionedComponentId());
        return connectable;
    }

    public ConnectableDTO createConnectableDto(final RemoteProcessGroupPortDTO remoteGroupPort, final ConnectableType type) {
        final ConnectableDTO connectable = new ConnectableDTO();
        connectable.setGroupId(remoteGroupPort.getGroupId());
        connectable.setId(remoteGroupPort.getId());
        connectable.setName(remoteGroupPort.getName());
        connectable.setType(type.name());
        connectable.setVersionedComponentId(connectable.getVersionedComponentId());
        return connectable;
    }

    /**
     *
     * @param original orig
     * @param deep if <code>true</code>, all Connections, ProcessGroups, Ports, Processors, etc. will be copied. If <code>false</code>, the copy will have links to the same objects referenced by
     * <code>original</code>.
     *
     * @return dto
     */
    private FlowSnippetDTO copy(final FlowSnippetDTO original, final boolean deep) {
        final FlowSnippetDTO copy = new FlowSnippetDTO();

        final Set<ConnectionDTO> connections = new LinkedHashSet<>();
        final Set<ProcessGroupDTO> groups = new LinkedHashSet<>();
        final Set<PortDTO> inputPorts = new LinkedHashSet<>();
        final Set<PortDTO> outputPorts = new LinkedHashSet<>();
        final Set<LabelDTO> labels = new LinkedHashSet<>();
        final Set<ProcessorDTO> processors = new LinkedHashSet<>();
        final Set<RemoteProcessGroupDTO> remoteProcessGroups = new LinkedHashSet<>();
        final Set<FunnelDTO> funnels = new LinkedHashSet<>();
        final Set<ControllerServiceDTO> controllerServices = new LinkedHashSet<>();

        if (deep) {
            for (final ProcessGroupDTO group : original.getProcessGroups()) {
                groups.add(copy(group, deep));
            }

            for (final PortDTO port : original.getInputPorts()) {
                inputPorts.add(copy(port));
            }

            for (final PortDTO port : original.getOutputPorts()) {
                outputPorts.add(copy(port));
            }

            for (final LabelDTO label : original.getLabels()) {
                labels.add(copy(label));
            }

            for (final ProcessorDTO processor : original.getProcessors()) {
                processors.add(copy(processor));
            }

            for (final RemoteProcessGroupDTO remoteGroup : original.getRemoteProcessGroups()) {
                remoteProcessGroups.add(copy(remoteGroup));
            }

            for (final FunnelDTO funnel : original.getFunnels()) {
                funnels.add(copy(funnel));
            }

            for (final ConnectionDTO connection : original.getConnections()) {
                connections.add(copy(connection));
            }

            for (final ControllerServiceDTO controllerService : original.getControllerServices()) {
                controllerServices.add(copy(controllerService));
            }
        } else {
            if (original.getConnections() != null) {
                connections.addAll(copy(original.getConnections()));
            }
            if (original.getProcessGroups() != null) {
                groups.addAll(copy(original.getProcessGroups()));
            }
            if (original.getInputPorts() != null) {
                inputPorts.addAll(copy(original.getInputPorts()));
            }
            if (original.getOutputPorts() != null) {
                outputPorts.addAll(copy(original.getOutputPorts()));
            }
            if (original.getLabels() != null) {
                labels.addAll(copy(original.getLabels()));
            }
            if (original.getProcessors() != null) {
                processors.addAll(copy(original.getProcessors()));
            }
            if (original.getRemoteProcessGroups() != null) {
                remoteProcessGroups.addAll(copy(original.getRemoteProcessGroups()));
            }
            if (original.getFunnels() != null) {
                funnels.addAll(copy(original.getFunnels()));
            }
            if (original.getControllerServices() != null) {
                controllerServices.addAll(copy(original.getControllerServices()));
            }
        }

        copy.setConnections(connections);
        copy.setProcessGroups(groups);
        copy.setInputPorts(inputPorts);
        copy.setLabels(labels);
        copy.setOutputPorts(outputPorts);
        copy.setProcessors(processors);
        copy.setRemoteProcessGroups(remoteProcessGroups);
        copy.setFunnels(funnels);
        copy.setControllerServices(controllerServices);

        return copy;
    }

    /**
     * Factory method for creating a new RevisionDTO based on this controller.
     *
     * @param lastMod mod
     * @return dto
     */
    public RevisionDTO createRevisionDTO(final FlowModification lastMod) {
        final Revision revision = lastMod.getRevision();

        // create the dto
        final RevisionDTO revisionDTO = new RevisionDTO();
        revisionDTO.setVersion(revision.getVersion());
        revisionDTO.setClientId(revision.getClientId());
        revisionDTO.setLastModifier(lastMod.getLastModifier());

        return revisionDTO;
    }

    public RevisionDTO createRevisionDTO(final Revision revision) {
        final RevisionDTO dto = new RevisionDTO();
        dto.setVersion(revision.getVersion());
        dto.setClientId(revision.getClientId());
        return dto;
    }

    public NodeDTO createNodeDTO(final NodeIdentifier nodeId, final NodeConnectionStatus status, final NodeHeartbeat nodeHeartbeat, final List<NodeEvent> events, final Set<String> roles) {
        final NodeDTO nodeDto = new NodeDTO();

        // populate node dto
        nodeDto.setNodeId(nodeId.getId());
        nodeDto.setAddress(nodeId.getApiAddress());
        nodeDto.setApiPort(nodeId.getApiPort());
        nodeDto.setStatus(status.getState().name());
        nodeDto.setRoles(roles);
        if (status.getConnectionRequestTime() != null) {
            final Date connectionRequested = new Date(status.getConnectionRequestTime());
            nodeDto.setConnectionRequested(connectionRequested);
        }

        // only connected nodes have heartbeats
        if (nodeHeartbeat != null) {
            final Date heartbeat = new Date(nodeHeartbeat.getTimestamp());
            nodeDto.setHeartbeat(heartbeat);
            nodeDto.setNodeStartTime(new Date(nodeHeartbeat.getSystemStartTime()));
            nodeDto.setActiveThreadCount(nodeHeartbeat.getActiveThreadCount());
            nodeDto.setQueued(FormatUtils.formatCount(nodeHeartbeat.getFlowFileCount()) + " / " + FormatUtils.formatDataSize(nodeHeartbeat.getFlowFileBytes()));
        }

        // populate node events
        final List<NodeEvent> nodeEvents = new ArrayList<>(events);
        Collections.sort(nodeEvents, new Comparator<NodeEvent>() {
            @Override
            public int compare(final NodeEvent event1, final NodeEvent event2) {
                return new Date(event2.getTimestamp()).compareTo(new Date(event1.getTimestamp()));
            }
        });

        // create the node event dtos
        final List<NodeEventDTO> nodeEventDtos = new ArrayList<>();
        for (final NodeEvent event : nodeEvents) {
            // create node event dto
            final NodeEventDTO nodeEventDto = new NodeEventDTO();
            nodeEventDtos.add(nodeEventDto);

            // populate node event dto
            nodeEventDto.setMessage(event.getMessage());
            nodeEventDto.setCategory(event.getSeverity().name());
            nodeEventDto.setTimestamp(new Date(event.getTimestamp()));
        }
        nodeDto.setEvents(nodeEventDtos);

        return nodeDto;
    }

    public RegistryDTO createRegistryDto(FlowRegistry registry) {
        final RegistryDTO dto = new RegistryDTO();
        dto.setDescription(registry.getDescription());
        dto.setId(registry.getIdentifier());
        dto.setName(registry.getName());
        dto.setUri(registry.getURL());
        return dto;
    }


    /* setters */
    public void setControllerServiceProvider(final ControllerServiceProvider controllerServiceProvider) {
        this.controllerServiceProvider = controllerServiceProvider;
    }

    public void setAuthorizer(final Authorizer authorizer) {
        this.authorizer = authorizer;
    }

    public void setEntityFactory(final EntityFactory entityFactory) {
        this.entityFactory = entityFactory;
    }

    public void setBulletinRepository(BulletinRepository bulletinRepository) {
        this.bulletinRepository = bulletinRepository;
    }

    public void setExtensionManager(ExtensionManager extensionManager) {
        this.extensionManager = extensionManager;
    }
}
