Scufl2Tools { public Configuration setAsNestedWorkflow(Processor processor, Workflow childWorkflow, Profile profile) { if(processor.getParent() == null) { throw new IllegalStateException("Processor " + processor + " has no parent"); } if(processor.getParent().getParent() != childWorkflow.getParent()) { throw new IllegalStateException( "Processor " + processor + " and workflow " + childWorkflow + " are not in the same Workflow bundle"); } if(nestedWorkflowForProcessor(processor, profile) != null) { throw new IllegalStateException("Processor " + processor + " already has a nested workflow"); } List<ProcessorBinding> processorBindings = processorBindingsForProcessor(processor, profile); if(processorBindings.size() != 0) { throw new IllegalStateException("Processor " + processor + "already has a binding"); } Activity activity = createActivityFromProcessor(processor, profile); activity.setType(NESTED_WORKFLOW); Configuration configuration = createConfigurationFor(activity, NESTED_WORKFLOW); ObjectNode json = configuration.getJsonAsObjectNode(); json.put("nestedWorkflow", childWorkflow.getName()); childWorkflow.setParent(processor.getParent().getParent()); return configuration; }  List<Annotation> annotationsFor(Child<?> bean); List<Annotation> annotationsFor(WorkflowBean bean,
			WorkflowBundle bundle); Configuration configurationFor(Configurable configurable,
			Profile profile); Configuration configurationForActivityBoundToProcessor(
			Processor processor, Profile profile); List<Configuration> configurationsFor(Configurable configurable,
			Profile profile); @SuppressWarnings("unchecked") List<BlockingControlLink> controlLinksBlocking(Processor blocked); @SuppressWarnings("unchecked") List<BlockingControlLink> controlLinksWaitingFor(
			Processor untilFinished); @SuppressWarnings("unchecked") List<DataLink> datalinksFrom(SenderPort senderPort); @SuppressWarnings("unchecked") List<DataLink> datalinksTo(ReceiverPort receiverPort); T findParent(Class<T> parentClass,
			Child<?> child); JsonNode portDefinitionFor(ActivityPort activityPort, Profile profile); ProcessorBinding processorBindingForProcessor(Processor processor,
			Profile profile); List<ProcessorBinding> processorBindingsForProcessor(
			Processor processor, Profile profile); List<ProcessorBinding> processorBindingsToActivity(Activity activity); ProcessorInputPortBinding processorPortBindingForPort(
			InputPort inputPort, Profile profile); ProcessorOutputPortBinding processorPortBindingForPort(
			OutputPort outputPort, Profile profile); void setParents(WorkflowBundle bundle); Set<Processor> possibleDownStreamProcessors(Workflow dataflow,
			Processor processor); Set<Processor> possibleUpStreamProcessors(Workflow dataflow,
			Processor firstProcessor); ProcessorSplit splitProcessors(Collection<Processor> processors,
			Processor splitPoint); Workflow nestedWorkflowForProcessor(Processor processor,
			Profile profile); List<Workflow> nestedWorkflowsForProcessor(Processor processor,
			Profile profile); boolean containsNestedWorkflow(Processor processor); boolean containsNestedWorkflow(Processor processor, Profile profile); void createActivityPortsFromProcessor(Activity activity,
			Processor processor); void createProcessorPortsFromActivity(Processor processor,
			Activity activity); ProcessorBinding bindActivityToProcessorByMatchingPorts(
			Activity activity, Processor processor); void bindActivityToProcessorByMatchingPorts(ProcessorBinding binding); ProcessorBinding createProcessorAndBindingFromActivity(
			Activity activity); Activity createActivityFromProcessor(Processor processor,
			Profile profile); Configuration setAsNestedWorkflow(Processor processor, Workflow childWorkflow, Profile profile); void removePortsBindingForUnknownPorts(ProcessorBinding binding); void updateBindingByMatchingPorts(ProcessorBinding binding); Processor createConstant(Workflow workflow, Profile profile,
			String name); Configuration createConfigurationFor(Activity activity,
			URI configType); Configuration createConfigurationFor(Processor processor,
			Profile profile); void setConstantStringValue(Processor constant, String value,
			Profile profile); String getConstantStringValue(Processor constant, Profile profile); Set<Processor> getConstants(Workflow workflow, Profile profile); void createDefaultIterationStrategyStack(Processor p); static URI PORT_DEFINITION; static URI NESTED_WORKFLOW; static URI CONSTANT; static URI CONSTANT_CONFIG; }
@Test public void testNestedProcessHasCorrectStructure() { Workflow child = new Workflow(); child.setName("childWorkflow"); child.setParent(workflowBundle); Workflow mainWorkflow = workflowBundle.getMainWorkflow(); Processor processor = new Processor(); processor.setParent(mainWorkflow); Profile profile = workflowBundle.getMainProfile(); Scufl2Tools tools = new Scufl2Tools(); tools.setAsNestedWorkflow(processor, child, profile); Set<String> processorInputNames = processor.getInputPorts().stream().map(InputProcessorPort::getName).collect(Collectors.toSet()); Set<String> workflowInputNames = child.getInputPorts().stream().map(InputWorkflowPort::getName).collect(Collectors.toSet()); assertEquals(workflowInputNames, processorInputNames); Set<String> processorOutputNames = processor.getOutputPorts().stream().map(OutputProcessorPort::getName).collect(Collectors.toSet()); Set<String> workflowOutputNames = child.getOutputPorts().stream().map(OutputWorkflowPort::getName).collect(Collectors.toSet()); assertEquals(workflowOutputNames, processorOutputNames); }