class DatabaseFDFlowManager extends BaseService implements FDFlowManager {

    @Override
    public FDFlowMetadata createFlow(final String agentClass, final NiFiUser user) {
        if (StringUtils.isBlank(agentClass)) {
            throw new IllegalArgumentException("Agent class cannot be null or blank");
        }

        if (user == null || StringUtils.isBlank(user.getIdentity())) {
            throw new IllegalArgumentException("A user identity must be provided");
        }

        // Create the initial root process group for the flow
        final VersionedProcessGroup flowContent = new VersionedProcessGroup();
        flowContent.setIdentifier(UUID.randomUUID().toString());
        flowContent.setName(ROOT_PROCESS_GROUP_NAME);

        // Save the flow entity to the db
        final FDFlowEntity flowEntity = new FDFlowEntity();
        flowEntity.setId(UUID.randomUUID().toString());
        flowEntity.setAgentClass(agentClass);
        flowEntity.setRootProcessGroupId(flowContent.getIdentifier());

        final FDFlowEntity savedFlowEntity = flowRepository.save(flowEntity);

        // Create the flow event for the initial flow
        final FDFlowEventEntity flowEventEntity = new FDFlowEventEntity();
        flowEventEntity.setId(UUID.randomUUID().toString());
        flowEventEntity.setFlow(savedFlowEntity);
        flowEventEntity.setEventType(FDFlowEventType.COMPONENT_ADDED);
        flowEventEntity.setEventDescription("Created root process group");
        flowEventEntity.setComponentId(flowContent.getIdentifier());
        flowEventEntity.setFlowRevision(BigInteger.ZERO);
        flowEventEntity.setUserIdentity(user.getIdentity());

        // Set the initial NiFi Registry info
        flowEventEntity.setRegistryUrl(UNPUBLISHED);
        flowEventEntity.setRegistryBucketId(UNPUBLISHED);
        flowEventEntity.setRegistryFlowId(UNPUBLISHED);
        flowEventEntity.setRegistryVersion(0);
        flowEventEntity.setLastPublished(null);
        flowEventEntity.setLastPublishedUserIdentity(null);

        // Serialize the flow content and set it in the flow event
        final String serializedFlowContent = serializeFlowContent(flowContent);
        flowEventEntity.setFlowContent(serializedFlowContent);
        flowEventEntity.setFlowFormat(CURRENT_FLOW_FORMAT);

        // Save the initial flow event to the db
        flowEventRepository.save(flowEventEntity);

        return modelMapper.map(savedFlowEntity, FDFlowMetadata.class);
    }

    @Autowired public  DatabaseFDFlowManager(final FDFlowRepository flowRepository,
                                 final FDFlowEventRepository flowEventRepository,
                                 final OptionalModelMapper modelMapper,
                                 final ObjectMapper objectMapper,
                                 final Validator validator);

}