http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/c5d452c1/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java ---------------------------------------------------------------------- diff --cc nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index 0000000,9a2dc30..027bae0 mode 000000,100644..100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@@ -1,0 -1,2142 +1,2268 @@@ + /* + * 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 java.text.Collator; + 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.LinkedHashMap; + import java.util.LinkedHashSet; + import java.util.List; + import java.util.Locale; + import java.util.Map; + import java.util.Set; + import java.util.TreeMap; + import java.util.TreeSet; + import java.util.concurrent.TimeUnit; + + import javax.ws.rs.WebApplicationException; + + import org.apache.nifi.action.Action; + import org.apache.nifi.action.component.details.ComponentDetails; + import org.apache.nifi.action.component.details.ProcessorDetails; + 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.MoveDetails; + import org.apache.nifi.action.details.PurgeDetails; + import org.apache.nifi.authorization.Authority; + import org.apache.nifi.cluster.HeartbeatPayload; + import org.apache.nifi.cluster.event.Event; + import org.apache.nifi.cluster.node.Node; + import org.apache.nifi.cluster.protocol.NodeIdentifier; + import org.apache.nifi.components.AllowableValue; + import org.apache.nifi.components.PropertyDescriptor; + import org.apache.nifi.components.ValidationResult; + 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.ControllerService; + import org.apache.nifi.controller.ControllerServiceLookup; + import org.apache.nifi.controller.Counter; + import org.apache.nifi.controller.ProcessorNode; + import org.apache.nifi.controller.Snippet; + import org.apache.nifi.controller.Template; + import org.apache.nifi.controller.label.Label; + 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.diagnostics.GarbageCollection; + import org.apache.nifi.diagnostics.StorageUsage; + import org.apache.nifi.diagnostics.SystemDiagnostics; + import org.apache.nifi.flowfile.FlowFilePrioritizer; + import org.apache.nifi.groups.ProcessGroup; + import org.apache.nifi.groups.ProcessGroupCounts; + import org.apache.nifi.groups.RemoteProcessGroup; + import org.apache.nifi.history.History; + import org.apache.nifi.processor.Processor; + import org.apache.nifi.processor.Relationship; + import org.apache.nifi.processor.annotation.CapabilityDescription; + import org.apache.nifi.processor.annotation.Tags; + 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.remote.RemoteGroupPort; + import org.apache.nifi.remote.RootGroupPort; + import org.apache.nifi.reporting.Bulletin; + import org.apache.nifi.reporting.BulletinRepository; + import org.apache.nifi.scheduling.SchedulingStrategy; + import org.apache.nifi.user.NiFiUser; + import org.apache.nifi.user.NiFiUserGroup; + import org.apache.nifi.util.FormatUtils; + import org.apache.nifi.util.NiFiProperties; + import org.apache.nifi.web.Revision; + import org.apache.nifi.web.api.dto.ProcessorConfigDTO.AllowableValueDTO; + import org.apache.nifi.web.api.dto.ProcessorConfigDTO.PropertyDescriptorDTO; + 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.ProcessorDetailsDTO; + 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.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.ConnectionStatusDTO; + import org.apache.nifi.web.api.dto.status.PortStatusDTO; + import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO; + import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO; + import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO; + import org.apache.nifi.web.api.dto.status.StatusDTO; + import org.apache.commons.lang3.StringUtils; + + /** + * + */ + public final class DtoFactory { + + @SuppressWarnings("rawtypes") + private final static Comparator<Class> CLASS_NAME_COMPARATOR = new Comparator<Class>() { + @Override + public int compare(Class class1, Class class2) { + return Collator.getInstance(Locale.US).compare(class1.getSimpleName(), class2.getSimpleName()); + } + }; + + final int MAX_BULLETINS_PER_COMPONENT = 5; + + private NiFiProperties properties; + private ControllerServiceLookup controllerServiceLookup; + + /** + * Creates an ActionDTO for the specified Action. + * + * @param action + * @return + */ + 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().name()); + actionDto.setTimestamp(action.getTimestamp()); + actionDto.setUserDn(action.getUserDn()); + actionDto.setUserName(action.getUserName()); + actionDto.setOperation(action.getOperation().name()); + actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails())); + actionDto.setComponentDetails(createComponentDetailsDto(action.getComponentDetails())); + + return actionDto; + } + + /** + * Creates an ActionDetailsDTO for the specified ActionDetails. + * + * @param actionDetails + * @return + */ + private ActionDetailsDTO createActionDetailsDto(final ActionDetails actionDetails) { + if (actionDetails == null) { + return null; + } + + if (actionDetails instanceof ConfigureDetails) { + 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 ConnectDetails) { + 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 MoveDetails) { + 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 PurgeDetails) { + 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 + * @return + */ + private ComponentDetailsDTO createComponentDetailsDto(final ComponentDetails componentDetails) { + if (componentDetails == null) { + return null; + } + + if (componentDetails instanceof ProcessorDetails) { + final ProcessorDetailsDTO processorDetails = new ProcessorDetailsDTO(); + processorDetails.setType(((ProcessorDetails) componentDetails).getType()); + return processorDetails; + } else if (componentDetails instanceof RemoteProcessGroupDetails) { + 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 + * @return + */ + public HistoryDTO createHistoryDto(final History history) { + final HistoryDTO historyDto = new HistoryDTO(); + historyDto.setTotal(history.getTotal()); + historyDto.setLastRefreshed(history.getLastRefreshed()); + + if (history.getActions() != null) { + List<ActionDTO> actionDtos = new ArrayList<>(); + for (Action action : history.getActions()) { + actionDtos.add(createActionDto(action)); + } + historyDto.setActions(actionDtos); + } + + return historyDto; + } + + /** + * Creates CounterDTOs for each Counter specified. + * + * @param counterDtos + * @return + */ + public CountersDTO createCountersDto(final Collection<CounterDTO> counterDtos) { + final CountersDTO dto = new CountersDTO(); + dto.setCounters(counterDtos); + dto.setGenerated(new Date()); + return dto; + } + + /** + * Creates a CounterDTO from the specified Counter. + * + * @param counter + * @return + */ + 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 + * @return + */ + public PositionDTO createPositionDto(final Position position) { + return new PositionDTO(position.getX(), position.getY()); + } + + /** + * Creates a ConnectionDTO from the specified Connection. + * + * @param connection + * @return + */ + 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.setBackPressureObjectThreshold(connection.getFlowFileQueue().getBackPressureObjectThreshold()); + dto.setBackPressureDataSizeThreshold(connection.getFlowFileQueue().getBackPressureDataSizeThreshold()); + dto.setFlowFileExpiration(connection.getFlowFileQueue().getFlowFileExpiration()); + dto.setPrioritizers(new ArrayList<String>()); + for (final FlowFilePrioritizer comparator : connection.getFlowFileQueue().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()); + } + } + + return dto; + } + + /** + * Creates a ConnectableDTO from the specified Connectable. + * + * @param connectable + * @return + */ + public ConnectableDTO createConnectableDto(final Connectable connectable) { + if (connectable == null) { + return null; + } + + final ConnectableDTO dto = new ConnectableDTO(); + dto.setId(connectable.getIdentifier()); + dto.setName(connectable.getName()); + dto.setType(connectable.getConnectableType().name()); + + 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()); + dto.setComments(remoteGroup.getComments()); + } else { + dto.setGroupId(connectable.getProcessGroup().getIdentifier()); + dto.setRunning(connectable.isRunning()); + dto.setComments(connectable.getComments()); + } + + return dto; + } + + /** + * Creates a LabelDTO from the specified Label. + * + * @param label + * @return + */ + 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()); + + return dto; + } + + /** + * Creates a FunnelDTO from the specified Funnel. + * + * @param funnel + * @return + */ + 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()); + + return dto; + } + + /** + * Creates a SnippetDTO from the specified Snippet. + * + * @param snippet + * @return + */ + public SnippetDTO createSnippetDto(final Snippet snippet) { + final SnippetDTO dto = new SnippetDTO(); + dto.setId(snippet.getId()); + dto.setParentGroupId(snippet.getParentGroupId()); + dto.setLinked(snippet.isLinked()); + + // populate the snippet contents ids + dto.setConnections(copy(snippet.getConnections())); + dto.setFunnels(copy(snippet.getFunnels())); + dto.setInputPorts(copy(snippet.getInputPorts())); + dto.setLabels(copy(snippet.getLabels())); + dto.setOutputPorts(copy(snippet.getOutputPorts())); + dto.setProcessGroups(copy(snippet.getProcessGroups())); + dto.setProcessors(copy(snippet.getProcessors())); + dto.setRemoteProcessGroups(copy(snippet.getRemoteProcessGroups())); + + return dto; + } + + /** + * Creates a TemplateDTO from the specified template. + * + * @param template + * @return + */ + 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.setName(original.getName()); + copy.setDescription(original.getDescription()); + copy.setTimestamp(original.getTimestamp()); + copy.setUri(original.getUri()); + return copy; + } + + private String formatCount(final Integer intStatus) { + return intStatus == null ? "-" : FormatUtils.formatCount(intStatus); + } + + private String formatDataSize(final Long longStatus) { + return longStatus == null ? "-" : FormatUtils.formatDataSize(longStatus); + } + + public RemoteProcessGroupStatusDTO createRemoteProcessGroupStatusDto(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.setActiveThreadCount(remoteProcessGroupStatus.getActiveThreadCount()); + dto.setSent(formatCount(remoteProcessGroupStatus.getSentCount()) + " / " + formatDataSize(remoteProcessGroupStatus.getSentContentSize())); + dto.setReceived(formatCount(remoteProcessGroupStatus.getReceivedCount()) + " / " + formatDataSize(remoteProcessGroupStatus.getReceivedContentSize())); + dto.setAuthorizationIssues(remoteProcessGroupStatus.getAuthorizationIssues()); + + return dto; + } + + public ProcessGroupStatusDTO createProcessGroupStatusDto(final BulletinRepository bulletinRepository, final ProcessGroupStatus processGroupStatus) { + + final ProcessGroupStatusDTO processGroupStatusDto = new ProcessGroupStatusDTO(); + processGroupStatusDto.setId(processGroupStatus.getId()); + processGroupStatusDto.setName(processGroupStatus.getName()); + processGroupStatusDto.setStatsLastRefreshed(new Date(processGroupStatus.getCreationTimestamp())); + processGroupStatusDto.setQueued(formatCount(processGroupStatus.getQueuedCount()) + " / " + formatDataSize(processGroupStatus.getQueuedContentSize())); + processGroupStatusDto.setRead(formatDataSize(processGroupStatus.getBytesRead())); + processGroupStatusDto.setWritten(formatDataSize(processGroupStatus.getBytesWritten())); + processGroupStatusDto.setInput(formatCount(processGroupStatus.getInputCount()) + " / " + formatDataSize(processGroupStatus.getInputContentSize())); + processGroupStatusDto.setOutput(formatCount(processGroupStatus.getOutputCount()) + " / " + formatDataSize(processGroupStatus.getOutputContentSize())); + processGroupStatusDto.setActiveThreadCount(processGroupStatus.getActiveThreadCount()); + + final Map<String, StatusDTO> componentStatusDtoMap = new HashMap<>(); + + // processor status + final Collection<ProcessorStatusDTO> processorStatDtoCollection = new ArrayList<>(); + processGroupStatusDto.setProcessorStatus(processorStatDtoCollection); + final Collection<ProcessorStatus> processorStatusCollection = processGroupStatus.getProcessorStatus(); + if (processorStatusCollection != null) { + for (final ProcessorStatus processorStatus : processorStatusCollection) { + final ProcessorStatusDTO processorStatusDto = createProcessorStatusDto(processorStatus); + processorStatDtoCollection.add(processorStatusDto); + componentStatusDtoMap.put(processorStatusDto.getId(), processorStatusDto); + } + } + + // connection status + final Collection<ConnectionStatusDTO> connectionStatusDtoCollection = new ArrayList<>(); + processGroupStatusDto.setConnectionStatus(connectionStatusDtoCollection); + final Collection<ConnectionStatus> connectionStatusCollection = processGroupStatus.getConnectionStatus(); + if (connectionStatusCollection != null) { + for (final ConnectionStatus connectionStatus : connectionStatusCollection) { + final ConnectionStatusDTO connectionStatusDto = createConnectionStatusDto(connectionStatus); + connectionStatusDtoCollection.add(connectionStatusDto); + } + } + + // local child process groups + final Collection<ProcessGroupStatusDTO> childProcessGroupStatusDtoCollection = new ArrayList<>(); + processGroupStatusDto.setProcessGroupStatus(childProcessGroupStatusDtoCollection); + final Collection<ProcessGroupStatus> childProcessGroupStatusCollection = processGroupStatus.getProcessGroupStatus(); + if (childProcessGroupStatusCollection != null) { + for (final ProcessGroupStatus childProcessGroupStatus : childProcessGroupStatusCollection) { + final ProcessGroupStatusDTO childProcessGroupStatusDto = createProcessGroupStatusDto(bulletinRepository, childProcessGroupStatus); + childProcessGroupStatusDtoCollection.add(childProcessGroupStatusDto); + } + } + + // remote child process groups + final Collection<RemoteProcessGroupStatusDTO> childRemoteProcessGroupStatusDtoCollection = new ArrayList<>(); + processGroupStatusDto.setRemoteProcessGroupStatus(childRemoteProcessGroupStatusDtoCollection); + final Collection<RemoteProcessGroupStatus> childRemoteProcessGroupStatusCollection = processGroupStatus.getRemoteProcessGroupStatus(); + if (childRemoteProcessGroupStatusCollection != null) { + for (final RemoteProcessGroupStatus childRemoteProcessGroupStatus : childRemoteProcessGroupStatusCollection) { + final RemoteProcessGroupStatusDTO childRemoteProcessGroupStatusDto = createRemoteProcessGroupStatusDto(childRemoteProcessGroupStatus); + childRemoteProcessGroupStatusDtoCollection.add(childRemoteProcessGroupStatusDto); + componentStatusDtoMap.put(childRemoteProcessGroupStatusDto.getId(), childRemoteProcessGroupStatusDto); + } + } + + // input ports + final Collection<PortStatusDTO> inputPortStatusDtoCollection = new ArrayList<>(); + processGroupStatusDto.setInputPortStatus(inputPortStatusDtoCollection); + final Collection<PortStatus> inputPortStatusCollection = processGroupStatus.getInputPortStatus(); + if (inputPortStatusCollection != null) { + for (final PortStatus portStatus : inputPortStatusCollection) { + final PortStatusDTO portStatusDto = createPortStatusDto(portStatus); + inputPortStatusDtoCollection.add(portStatusDto); + componentStatusDtoMap.put(portStatusDto.getId(), portStatusDto); + } + } + + // output ports + final Collection<PortStatusDTO> outputPortStatusDtoCollection = new ArrayList<>(); + processGroupStatusDto.setOutputPortStatus(outputPortStatusDtoCollection); + final Collection<PortStatus> outputPortStatusCollection = processGroupStatus.getOutputPortStatus(); + if (outputPortStatusCollection != null) { + for (final PortStatus portStatus : outputPortStatusCollection) { + final PortStatusDTO portStatusDto = createPortStatusDto(portStatus); + outputPortStatusDtoCollection.add(portStatusDto); + componentStatusDtoMap.put(portStatusDto.getId(), portStatusDto); + } + } + + // get the bulletins for this group and associate with the specific child component + if (bulletinRepository != null) { + if (processGroupStatusDto.getBulletins() == null) { + processGroupStatusDto.setBulletins(new ArrayList<BulletinDTO>()); + } + + // locate bulletins for this process group + final List<Bulletin> results = bulletinRepository.findBulletinsForGroupBySource(processGroupStatus.getId(), MAX_BULLETINS_PER_COMPONENT); + for (final Bulletin bulletin : results) { + final StatusDTO status = componentStatusDtoMap.get(bulletin.getSourceId()); + + // ensure this connectable is still in the flow + if (status != null) { + if (status.getBulletins() == null) { + status.setBulletins(new ArrayList<BulletinDTO>()); + } + + // convert the result into a dto + final BulletinDTO bulletinDto = createBulletinDto(bulletin); + status.getBulletins().add(bulletinDto); + + // create a copy for the parent group + final BulletinDTO copy = copy(bulletinDto); + copy.setGroupId(StringUtils.EMPTY); + copy.setSourceId(processGroupStatus.getId()); + copy.setSourceName(processGroupStatus.getName()); + processGroupStatusDto.getBulletins().add(copy); + } + } + + // copy over descendant bulletins + for (final ProcessGroupStatusDTO childProcessGroupStatusDto : processGroupStatusDto.getProcessGroupStatus()) { + if (childProcessGroupStatusDto.getBulletins() != null) { + for (final BulletinDTO descendantBulletinDto : childProcessGroupStatusDto.getBulletins()) { + // create a copy for the parent group + final BulletinDTO copy = copy(descendantBulletinDto); + copy.setGroupId(StringUtils.EMPTY); + copy.setSourceId(processGroupStatus.getId()); + copy.setSourceName(processGroupStatus.getName()); + processGroupStatusDto.getBulletins().add(copy); + } + } + } + + // sort the bulletins + Collections.sort(processGroupStatusDto.getBulletins(), new Comparator<BulletinDTO>() { + @Override + public int compare(BulletinDTO o1, BulletinDTO o2) { + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return 1; + } + if (o2 == null) { + return -1; + } + + return -Long.compare(o1.getId(), o2.getId()); + } + }); + + // prune the response to only include the max number of bulletins + if (processGroupStatusDto.getBulletins().size() > MAX_BULLETINS_PER_COMPONENT) { + processGroupStatusDto.setBulletins(processGroupStatusDto.getBulletins().subList(0, MAX_BULLETINS_PER_COMPONENT)); + } + } + + 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()); + + final String queuedCount = FormatUtils.formatCount(connectionStatus.getQueuedCount()); + final String queuedSize = FormatUtils.formatDataSize(connectionStatus.getQueuedBytes()); + connectionStatusDto.setQueuedCount(queuedCount); + connectionStatusDto.setQueuedSize(queuedSize); + connectionStatusDto.setQueued(queuedCount + " / " + queuedSize); + + final int inputCount = connectionStatus.getInputCount(); + final long inputBytes = connectionStatus.getInputBytes(); + connectionStatusDto.setInput(FormatUtils.formatCount(inputCount) + " / " + FormatUtils.formatDataSize(inputBytes)); + + final int outputCount = connectionStatus.getOutputCount(); + final long outputBytes = connectionStatus.getOutputBytes(); + connectionStatusDto.setOutput(FormatUtils.formatCount(outputCount) + " / " + FormatUtils.formatDataSize(outputBytes)); + + return connectionStatusDto; + } + + public ProcessorStatusDTO createProcessorStatusDto(final ProcessorStatus procStatus) { + + final ProcessorStatusDTO dto = new ProcessorStatusDTO(); + dto.setId(procStatus.getId()); + dto.setGroupId(procStatus.getGroupId()); + dto.setName(procStatus.getName()); + + final int processedCount = procStatus.getOutputCount(); + final long numProcessedBytes = procStatus.getOutputBytes(); + dto.setOutput(FormatUtils.formatCount(processedCount) + " / " + FormatUtils.formatDataSize(numProcessedBytes)); + + final int inputCount = procStatus.getInputCount(); + final long inputBytes = procStatus.getInputBytes(); + dto.setInput(FormatUtils.formatCount(inputCount) + " / " + FormatUtils.formatDataSize(inputBytes)); + + final long readBytes = procStatus.getBytesRead(); + dto.setRead(FormatUtils.formatDataSize(readBytes)); + + final long writtenBytes = procStatus.getBytesWritten(); + dto.setWritten(FormatUtils.formatDataSize(writtenBytes)); + + dto.setTasksDuration(FormatUtils.formatHoursMinutesSeconds(procStatus.getProcessingNanos(), TimeUnit.NANOSECONDS)); + dto.setTasks(FormatUtils.formatCount(procStatus.getInvocations())); + + // determine the run status + dto.setRunStatus(procStatus.getRunStatus().toString()); + + dto.setActiveThreadCount(procStatus.getActiveThreadCount()); + dto.setType(procStatus.getType()); + + return dto; + } + + /** + * Creates a PortStatusDTO for the specified PortStatus. + * + * @param portStatus + * @return + */ + public PortStatusDTO createPortStatusDto(final PortStatus portStatus) { + final PortStatusDTO dto = new PortStatusDTO(); + dto.setId(portStatus.getId()); + dto.setGroupId(portStatus.getGroupId()); + dto.setName(portStatus.getName()); + dto.setActiveThreadCount(portStatus.getActiveThreadCount()); + dto.setRunStatus(portStatus.getRunStatus().toString()); + dto.setTransmitting(portStatus.isTransmitting()); + + final int processedCount = portStatus.getOutputCount(); + final long numProcessedBytes = portStatus.getOutputBytes(); + dto.setOutput(FormatUtils.formatCount(processedCount) + " / " + FormatUtils.formatDataSize(numProcessedBytes)); + + final int inputCount = portStatus.getInputCount(); + final long inputBytes = portStatus.getInputBytes(); + dto.setInput(FormatUtils.formatCount(inputCount) + " / " + FormatUtils.formatDataSize(inputBytes)); + + return dto; + } + + /** + * Copies the specified snippet. + * + * @param originalSnippet + * @return + */ + public FlowSnippetDTO copySnippetContents(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)); + } + } + + return copySnippet; + } + + /** + * Creates a PortDTO from the specified Port. + * + * @param port + * @return + */ + 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()); + + // if this port is on the root group, determine if its actually connected to another nifi + if (port instanceof RootGroupPort) { + final RootGroupPort rootGroupPort = (RootGroupPort) port; + dto.setTransmitting(rootGroupPort.isTransmitting()); + dto.setGroupAccessControl(rootGroupPort.getGroupAccessControl()); + dto.setUserAccessControl(rootGroupPort.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 RemoteProcessGroupPortDTO createRemoteProcessGroupPortDto(final RemoteGroupPort port) { + if (port == null) { + return null; + } + + final RemoteProcessGroupPortDTO dto = new RemoteProcessGroupPortDTO(); + dto.setId(port.getIdentifier()); + 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()); + + // 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 + * @return + */ + public RemoteProcessGroupDTO createRemoteProcessGroupDto(final RemoteProcessGroup group) { + if (group == null) { + return null; + } + + final Set<RemoteProcessGroupPortDTO> inputPorts = new TreeSet<>(new DtoFactory.SortedRemoteGroupPortComparator()); + final Set<RemoteProcessGroupPortDTO> outputPorts = new TreeSet<>(new DtoFactory.SortedRemoteGroupPortComparator()); + + 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 { + activeRemoteOutputPortCount++; + } + } + } + + 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.setTargetUri(group.getTargetUri().toString()); + dto.setFlowRefreshed(group.getLastRefreshTime()); + dto.setContents(contents); + + // 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())); + } + + dto.setActiveRemoteInputPortCount(activeRemoteInputPortCount); + dto.setInactiveRemoteInputPortCount(inactiveRemoteInputPortCount); + dto.setActiveRemoteOutputPortCount(activeRemoteOutputPortCount); + dto.setInactiveRemoteOutputPortCount(inactiveRemoteOutputPortCount); + + final ProcessGroupCounts counts = group.getCounts(); + if (counts != null) { + dto.setInputPortCount(counts.getInputPortCount()); + dto.setOutputPortCount(counts.getOutputPortCount()); + } + + return dto; + } + + /** + * Creates a ProcessGroupDTO from the specified parent ProcessGroup. + * + * @param parentGroup + * @return + */ + private ProcessGroupDTO createParentProcessGroupDto(final ProcessGroup parentGroup) { + if (parentGroup == null) { + return null; + } + + final ProcessGroupDTO dto = new ProcessGroupDTO(); + dto.setId(parentGroup.getIdentifier()); + dto.setName(parentGroup.getName()); + + if (parentGroup.getParent() != null) { + dto.setParent(createParentProcessGroupDto(parentGroup.getParent())); + } + + return dto; + } + + /** + * Creates a ProcessGroupDTO from the specified ProcessGroup. + * + * @param group + * @return + */ + public ProcessGroupDTO createProcessGroupDto(final ProcessGroup group) { + return createProcessGroupDto(group, false); + } + + /** + * Creates a ProcessGroupDTO from the specified ProcessGroup. + * + * @param group + * @param recurse + * @return + */ + 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 + * @param recurse + * @return + */ + 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()); + + ProcessGroup parentGroup = group.getParent(); + if (parentGroup != null) { + dto.setParentGroupId(parentGroup.getIdentifier()); + dto.setParent(createParentProcessGroupDto(parentGroup)); + } + + final ProcessGroupCounts counts = group.getCounts(); + dto.setRunningCount(counts.getRunningCount()); + dto.setStoppedCount(counts.getStoppedCount()); + dto.setInvalidCount(counts.getInvalidCount()); + dto.setDisabledCount(counts.getDisabledCount()); + dto.setInputPortCount(counts.getInputPortCount()); + dto.setOutputPortCount(counts.getOutputPortCount()); + dto.setActiveRemotePortCount(counts.getActiveRemotePortCount()); + dto.setInactiveRemotePortCount(counts.getInactiveRemotePortCount()); + + return dto; + } + + /** + * Creates a ProcessGroupContentDTO from the specified ProcessGroup. + * + * @param group + * @param recurse + * @return + */ + 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; + } + + /** + * Gets the capability description from the specified class. + * + * @param cls + * @return + */ + private String getCapabilityDescription(final Class<?> cls) { + final CapabilityDescription description = cls.getAnnotation(CapabilityDescription.class); + return (description == null) ? null : description.value(); + } + + /** + * Gets the tags from the specified class. + * + * @param cls + * @return + */ + 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); + } + } + + return tags; + } + + /** + * Gets the DocumentedTypeDTOs from the specified classes. + * + * @param classes + * @return + */ + @SuppressWarnings("rawtypes") + public Set<DocumentedTypeDTO> fromDocumentedTypes(final Set<Class> classes) { + final Set<DocumentedTypeDTO> types = new LinkedHashSet<>(); + final Set<Class> sortedClasses = new TreeSet<>(CLASS_NAME_COMPARATOR); + sortedClasses.addAll(classes); + + for (final Class<?> cls : sortedClasses) { + final DocumentedTypeDTO type = new DocumentedTypeDTO(); + type.setType(cls.getName()); + type.setDescription(getCapabilityDescription(cls)); + type.setTags(getTags(cls)); + types.add(type); + } + + return types; + } ++ ++ /** ++ * Identifies all baseTypes for the specified type that are assignable to the specified baseType. ++ * ++ * @param baseType ++ * @param type ++ * @param baseTypes ++ */ ++ private void identifyBaseTypes(final Class baseType, final Class type, final Set<Class> baseTypes, final boolean recurse) { ++ final Class[] interfaces = type.getInterfaces(); ++ for (final Class i : interfaces) { ++ if (baseType.isAssignableFrom(i) && !baseType.equals(i)) { ++ baseTypes.add(i); ++ } ++ } ++ ++ if (recurse) { ++ if (type.getSuperclass() != null) { ++ identifyBaseTypes(baseType, type.getSuperclass(), baseTypes, recurse); ++ } ++ } ++ } ++ ++ /** ++ * Gets the DocumentedTypeDTOs from the specified classes for the specified baseClass. ++ * ++ * @param baseClass ++ * @param classes ++ * @return ++ */ ++ public Set<DocumentedTypeDTO> fromDocumentedTypes(final Class baseClass, final Set<Class> classes) { ++ final Set<DocumentedTypeDTO> types = new LinkedHashSet<>(); ++ final Set<Class> sortedClasses = new TreeSet<>(CLASS_NAME_COMPARATOR); ++ sortedClasses.addAll(classes); ++ ++ // identify all interfaces that extend baseClass for all classes ++ final Set<Class> interfaces = new HashSet<>(); ++ for (final Class<?> cls : sortedClasses) { ++ identifyBaseTypes(baseClass, cls, interfaces, true); ++ } ++ ++ // build a lookup of all interfaces ++ final Map<Class, DocumentedTypeDTO> lookup = new HashMap<>(); ++ ++ // convert the interfaces to DTO form ++ for (final Class<?> i : interfaces) { ++ final DocumentedTypeDTO type = new DocumentedTypeDTO(); ++ type.setType(i.getName()); ++ type.setDescription(getCapabilityDescription(i)); ++ type.setTags(getTags(i)); ++ type.setChildTypes(new LinkedHashSet<DocumentedTypeDTO>()); ++ lookup.put(i, type); ++ } ++ ++ // move the interfaces into the appropriate hierarchy ++ for (final Class<?> i : interfaces) { ++ // identify the base types ++ final Set<Class> baseTypes = new LinkedHashSet<>(); ++ identifyBaseTypes(baseClass, i, baseTypes, false); ++ ++ // move this interfaces into the hierarchy where appropriate ++ if (!baseTypes.isEmpty()) { ++ // get the DTO for each base type ++ for (final Class baseType : baseTypes) { ++ final DocumentedTypeDTO parentInteface = lookup.get(baseType); ++ final DocumentedTypeDTO childInterface = lookup.get(i); ++ ++ // include all parent tags in the respective children ++ childInterface.getTags().addAll(parentInteface.getTags()); ++ ++ // update the hierarchy ++ parentInteface.getChildTypes().add(childInterface); ++ } ++ ++ // remove this interface from the lookup (this will only ++ // leave the interfaces that are ancestor roots) ++ lookup.remove(i); ++ } ++ } ++ ++ // include the interfaces ++ sortedClasses.addAll(lookup.keySet()); ++ ++ // get the DTO form for all interfaces and classes ++ for (final Class<?> cls : sortedClasses) { ++ boolean add = false; ++ ++ final DocumentedTypeDTO type; ++ if (lookup.containsKey(cls)) { ++ type = lookup.get(cls); ++ add = true; ++ } else { ++ type = new DocumentedTypeDTO(); ++ type.setType(cls.getName()); ++ type.setDescription(getCapabilityDescription(cls)); ++ type.setTags(getTags(cls)); ++ } ++ ++ // identify the base types ++ final Set<Class> baseTypes = new LinkedHashSet<>(); ++ identifyBaseTypes(baseClass, cls, baseTypes, false); ++ ++ // include this type if it doesn't belong to another hierarchy ++ if (baseTypes.isEmpty()) { ++ add = true; ++ } else { ++ // get the DTO for each base type ++ for (final Class baseType : baseTypes) { ++ final DocumentedTypeDTO parentInteface = lookup.get(baseType); ++ ++ // include all parent tags in the respective children ++ type.getTags().addAll(parentInteface.getTags()); ++ ++ // update the hierarchy ++ parentInteface.getChildTypes().add(type); ++ } ++ } ++ ++ // add if appropriate ++ if (add) { ++ types.add(type); ++ } ++ } ++ ++ return types; ++ } + + /** + * Creates a ProcessorDTO from the specified ProcessorNode. + * + * @param node + * @return + */ + public ProcessorDTO createProcessorDto(final ProcessorNode node) { + if (node == null) { + return null; + } + + final ProcessorDTO dto = new ProcessorDTO(); + dto.setId(node.getIdentifier()); + dto.setPosition(createPositionDto(node.getPosition())); + dto.setStyle(node.getStyle()); + dto.setParentGroupId(node.getProcessGroup().getIdentifier()); + + dto.setType(node.getProcessor().getClass().getCanonicalName()); + 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 + Collections.sort(relationships, new Comparator<RelationshipDTO>() { + @Override + public int compare(RelationshipDTO r1, 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.setConfig(createProcessorConfigDto(node)); + + 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 + * @return + */ + public BulletinBoardDTO createBulletinBoardDto(final List<BulletinDTO> bulletins) { + // sort the bulletins + Collections.sort(bulletins, new Comparator<BulletinDTO>() { + @Override + public int compare(BulletinDTO bulletin1, BulletinDTO 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 a BulletinDTO for the specified Bulletin. + * + * @param bulletin + * @return + */ + 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 + * @return + */ + 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()); + dto.setClusterNodeIdentifier(node.getClusterNodeIdentifier()); + return dto; + } + + /** + * Creates a FlowFileNodeDTO for the specified LineageNode. + * + * @param node + * @return + */ + 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()); + dto.setClusterNodeIdentifier(node.getClusterNodeIdentifier()); + return dto; + } + + /** + * Creates a ProvenanceLinkDTO for the specified LineageEdge. + * + * @param edge + * @return + */ + 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 + * @return + */ + 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.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 + * @return + */ + public SystemDiagnosticsDTO createSystemDiagnosticsDto(final SystemDiagnostics sysDiagnostics) { + + final SystemDiagnosticsDTO dto = new SystemDiagnosticsDTO(); + dto.setStatsLastRefreshed(new Date(sysDiagnostics.getCreationTimestamp())); + + // processors + dto.setAvailableProcessors(sysDiagnostics.getAvailableProcessors()); + dto.setProcessorLoadAverage(sysDiagnostics.getProcessorLoadAverage()); + + // threads + dto.setDaemonThreads(sysDiagnostics.getDaemonThreads()); + dto.setTotalThreads(sysDiagnostics.getTotalThreads()); + + // heap + dto.setMaxHeap(FormatUtils.formatDataSize(sysDiagnostics.getMaxHeap())); + dto.setTotalHeap(FormatUtils.formatDataSize(sysDiagnostics.getTotalHeap())); + dto.setUsedHeap(FormatUtils.formatDataSize(sysDiagnostics.getUsedHeap())); + dto.setFreeHeap(FormatUtils.formatDataSize(sysDiagnostics.getFreeHeap())); + dto.setHeapUtilization(FormatUtils.formatUtilization(sysDiagnostics.getHeapUtilization())); + + // non heap + dto.setMaxNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getMaxNonHeap())); + dto.setTotalNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getTotalNonHeap())); + dto.setUsedNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getUsedNonHeap())); + dto.setFreeNonHeap(FormatUtils.formatDataSize(sysDiagnostics.getFreeNonHeap())); + dto.setNonHeapUtilization(FormatUtils.formatUtilization(sysDiagnostics.getNonHeapUtilization())); + + // flow file disk usage + final SystemDiagnosticsDTO.StorageUsageDTO flowFileRepositoryStorageUsageDto = createStorageUsageDTO(null, sysDiagnostics.getFlowFileRepositoryStorageUsage()); + dto.setFlowFileRepositoryStorageUsage(flowFileRepositoryStorageUsageDto); + + // content disk usage + final Set<SystemDiagnosticsDTO.StorageUsageDTO> contentRepositoryStorageUsageDtos = new LinkedHashSet<>(); + dto.setContentRepositoryStorageUsage(contentRepositoryStorageUsageDtos); + for (final Map.Entry<String, StorageUsage> entry : sysDiagnostics.getContentRepositoryStorageUsage().entrySet()) { + contentRepositoryStorageUsageDtos.add(createStorageUsageDTO(entry.getKey(), entry.getValue())); + } + + // garbage collection + final Set<SystemDiagnosticsDTO.GarbageCollectionDTO> garbageCollectionDtos = new LinkedHashSet<>(); + dto.setGarbageCollection(garbageCollectionDtos); + for (final Map.Entry<String, GarbageCollection> entry : sysDiagnostics.getGarbageCollection().entrySet()) { + garbageCollectionDtos.add(createGarbageCollectionDTO(entry.getKey(), entry.getValue())); + } + + return dto; + } + + /** + * Creates a StorageUsageDTO from the specified StorageUsage. + * + * @param identifier + * @param storageUsage + * @return + */ + public SystemDiagnosticsDTO.StorageUsageDTO createStorageUsageDTO(final String identifier, final StorageUsage storageUsage) { + final SystemDiagnosticsDTO.StorageUsageDTO dto = new SystemDiagnosticsDTO.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 + * @param garbageCollection + * @return + */ + public SystemDiagnosticsDTO.GarbageCollectionDTO createGarbageCollectionDTO(final String name, final GarbageCollection garbageCollection) { + final SystemDiagnosticsDTO.GarbageCollectionDTO dto = new SystemDiagnosticsDTO.GarbageCollectionDTO(); + dto.setName(name); + dto.setCollectionCount(garbageCollection.getCollectionCount()); + dto.setCollectionTime(FormatUtils.formatHoursMinutesSeconds(garbageCollection.getCollectionTime(), TimeUnit.MILLISECONDS)); + return dto; + } + + /** + * Creates a ProcessorConfigDTO from the specified ProcessorNode. + * + * @param procNode + * @return + */ + 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(PropertyDescriptor o1, PropertyDescriptor o2) { + return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName()); + } + }); + sortedProperties.putAll(procNode.getProperties()); + + // 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 (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)); + + // determine the property value - don't include sensitive properties + String propertyValue = entry.getValue(); + if (propertyValue != null && descriptor.isSensitive()) { + propertyValue = "********"; + } + + // 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.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 + * @return + */ + private ProcessorConfigDTO.PropertyDescriptorDTO createPropertyDescriptorDto(final PropertyDescriptor propertyDescriptor) { + if (propertyDescriptor == null) { + return null; + } + + final ProcessorConfigDTO.PropertyDescriptorDTO dto = new ProcessorConfigDTO.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()); + + final Class<? extends ControllerService> serviceDefinition = propertyDescriptor.getControllerServiceDefinition(); + if (propertyDescriptor.getAllowableValues() == null) { + if (serviceDefinition == null) { + dto.setAllowableValues(null); + } else { + final Set<AllowableValueDTO> allowableValues = new LinkedHashSet<>(); + for (final String serviceIdentifier : controllerServiceLookup.getControllerServiceIdentifiers(serviceDefinition)) { + String displayName = serviceIdentifier; + + // TODO: attempt to get the controller service name + final ControllerService controllerService = controllerServiceLookup.getControllerService(serviceIdentifier); + + final AllowableValueDTO allowableValue = new AllowableValueDTO(); + allowableValue.setDisplayName(displayName); + allowableValue.setValue(serviceIdentifier); + allowableValues.add(allowableValue); + } + dto.setAllowableValues(allowableValues); + } + } else { + final Set<AllowableValueDTO> allowableValues = new LinkedHashSet<>(); + 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(allowableValueDto); + } + dto.setAllowableValues(allowableValues); + } + + 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.setUri(original.getUri()); + + 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.setUri(original.getUri()); + + 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 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.setUri(original.getUri()); + copy.setSupportsParallelProcessing(original.getSupportsParallelProcessing()); + copy.setSupportsEventDriven(original.getSupportsEventDriven()); + copy.setValidationErrors(copy(original.getValidationErrors())); + + 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.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.setUri(original.getUri()); + copy.setzIndex(original.getzIndex()); + copy.setLabelIndex(original.getLabelIndex()); + copy.setBends(copy(original.getBends())); + + 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.setUri(original.getUri()); + 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())); + return copy; + } + + public RemoteProcessGroupPortDTO copy(final RemoteProcessGroupPortDTO original) { + final RemoteProcessGroupPortDTO copy = new RemoteProcessGroupPortDTO(); + copy.setId(original.getId()); + 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()); + 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.setInputPortCount(original.getInputPortCount()); + copy.setInvalidCount(original.getInvalidCount()); + copy.setName(original.getName()); + copy.setOutputPortCount(original.getOutputPortCount()); + copy.setParent(original.getParent()); + copy.setParentGroupId(original.getParentGroupId()); + + copy.setRunning(original.isRunning()); + copy.setRunningCount(original.getRunningCount()); + copy.setStoppedCount(original.getStoppedCount()); + copy.setDisabledCount(original.getDisabledCount()); + copy.setActiveRemotePortCount(original.getActiveRemotePortCount()); + copy.setInactiveRemotePortCount(original.getInactiveRemotePortCount()); + copy.setUri(original.getUri()); + + 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.setTargetUri(original.getTargetUri()); + copy.setUri(original.getUri()); + + copy.setContents(copyContents); + + return copy; + } + + public Connect
<TRUNCATED>
