@Override public Builder setRelationship(Relationship relationship) { this.relationship = relationship.getName(); return this; }
@Override public Relationship getRelationship(final String relationshipName) { if (PORT_RELATIONSHIP.getName().equals(relationshipName)) { return PORT_RELATIONSHIP; } return null; }
@Override public Relationship getRelationship(final String relationshipName) { return (Relationship.ANONYMOUS.getName().equals(relationshipName)) ? Relationship.ANONYMOUS : null; }
@Override public int compareTo(final Relationship o) { if (o == null) { return -1; } final String thisName = getName(); final String thatName = o.getName(); if (thisName == null && thatName == null) { return 0; } if (thisName == null) { return 1; } if (thatName == null) { return -1; } return thisName.compareTo(thatName); }
protected Relationship getRelationshipForName(String name, Set<Relationship> relationships) { for (Relationship relationship : relationships) { if (relationship.getName().equals(name)) { return relationship; } } throw new IllegalStateException("Unknown relationship " + name); }
@Override public Set<Connection> getConnections(final Relationship relationship) { readLock.lock(); try { if (relationship.equals(PORT_RELATIONSHIP)) { return Collections.unmodifiableSet(outgoingConnections); } throw new IllegalArgumentException("No relationship with name " + relationship.getName() + " exists for Local Ports"); } finally { readLock.unlock(); } }
@Override public void update(Map<String, Integer> loadInfo) { for (Relationship rel : relationshipsRef.get()) { String hostname = rel.getDescription(); Integer weight = 1; if (loadInfo.containsKey(hostname)) { weight = loadInfo.get(hostname); } weightings.put(Integer.decode(rel.getName()), weight); } updateWeightedRelationships(weightings); } };
@Override public Set<Connection> getConnections(final Relationship relationship) { readLock.lock(); try { if (relationship.equals(Relationship.ANONYMOUS)) { return Collections.unmodifiableSet(outgoingConnections); } throw new IllegalArgumentException("No relationship with name " + relationship.getName() + " exists for Funnels"); } finally { readLock.unlock(); } }
@Override public String getName() { String name = StandardConnection.this.getName(); final Collection<Relationship> relationships = getRelationships(); if (name == null && CollectionUtils.isNotEmpty(relationships)) { name = StringUtils.join(relationships.stream().map(relationship -> relationship.getName()).collect(Collectors.toSet()), ", "); } if (name == null) { name = "Connection"; } return name; }
@Override public void setAutoTerminatedRelationships(final Set<Relationship> terminate) { if (isRunning()) { throw new IllegalStateException("Cannot modify Processor configuration while the Processor is running"); } for (final Relationship rel : terminate) { if (!getConnections(rel).isEmpty()) { throw new IllegalStateException("Cannot mark relationship '" + rel.getName() + "' as auto-terminated because Connection already exists with this relationship"); } } undefinedRelationshipsToTerminate.set(new HashSet<>(terminate)); LOG.debug("Resetting Validation State of {} due to setting auto-terminated relationships", this); resetValidationState(); }
private void transferResult(final FlowFile flowFile, final Relationship result, final String detail, final Integer expectedOrder) { final Map<String, String> attributes = new HashMap<>(); attributes.put(ATTR_RESULT, result.getName()); if (expectedOrder != null) { attributes.put(ATTR_EXPECTED_ORDER, expectedOrder.toString()); } if (!isBlank(detail)) { attributes.put(ATTR_DETAIL, detail); } FlowFile resultFlowFile = processSession.putAllAttributes(flowFile, attributes); // Remove if (expectedOrder == null) { resultFlowFile = processSession.removeAttribute(resultFlowFile, ATTR_EXPECTED_ORDER); } if (detail == null) { resultFlowFile = processSession.removeAttribute(resultFlowFile, ATTR_DETAIL); } processSession.transfer(resultFlowFile, result); }
@Override public void transfer(FlowFile flowFile, final Relationship relationship) { if (relationship == Relationship.SELF) { transfer(flowFile); return; } if(!processor.getRelationships().contains(relationship)){ throw new IllegalArgumentException("this relationship " + relationship.getName() + " is not known"); } flowFile = validateState(flowFile); List<MockFlowFile> list = transferMap.computeIfAbsent(relationship, r -> new ArrayList<>()); beingProcessed.remove(flowFile.getId()); list.add((MockFlowFile) flowFile); updateLastQueuedDate((MockFlowFile) flowFile); }
@Override protected void addSupportedRelationships(Set<Relationship> relationships) { relationships.add(new Relationship.Builder().name(REL_SUCCESS.getName()) .description("All FlowFiles that are written to Couchbase Server are routed to this relationship.").build()); relationships.add(new Relationship.Builder().name(REL_RETRY.getName()) .description("All FlowFiles failed to be written to Couchbase Server but can be retried are routed to this relationship.").build()); relationships.add(new Relationship.Builder().name(REL_FAILURE.getName()) .description("All FlowFiles failed to be written to Couchbase Server and not retry-able are routed to this relationship.").build()); }
@Override protected void addSupportedRelationships(final Set<Relationship> relationships) { relationships.add(new Relationship.Builder().name(REL_ORIGINAL.getName()) .description("The original input FlowFile is routed to this relationship" + " when the value is retrieved from Couchbase Server and routed to 'success'.").build()); relationships.add(new Relationship.Builder().name(REL_SUCCESS.getName()) .description("Values retrieved from Couchbase Server are written as outgoing FlowFiles content" + " or put into an attribute of the incoming FlowFile and routed to this relationship.").build()); relationships.add(new Relationship.Builder().name(REL_RETRY.getName()) .description("All FlowFiles failed to fetch from Couchbase Server but can be retried are routed to this relationship.").build()); relationships.add(new Relationship.Builder().name(REL_FAILURE.getName()) .description("All FlowFiles failed to fetch from Couchbase Server and not retry-able are routed to this relationship.").build()); }
/** * Asserts that all FlowFiles meet all conditions. * * @param relationship relationship * @param predicate conditions */ @Override public void assertAllConditionsMet(final Relationship relationship, Predicate<MockFlowFile> predicate) { if (predicate==null) { Assert.fail("predicate cannot be null"); } final List<MockFlowFile> flowFiles = getFlowFilesForRelationship(relationship); if (flowFiles.isEmpty()) { Assert.fail("Relationship " + relationship.getName() + " does not contain any FlowFile"); } for (MockFlowFile flowFile : flowFiles) { if (predicate.test(flowFile)==false) { Assert.fail("FlowFile " + flowFile + " does not meet all condition"); } } }
@Override protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) { if (propertyDescriptorName.equals(REL_NO_MATCH.getName())) { return null; } return new PropertyDescriptor.Builder() .required(false) .name(propertyDescriptorName) .addValidator(StandardValidators.createRegexValidator(0, Integer.MAX_VALUE, true)) .dynamic(true) .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES) .build(); }
/** * Create an {@link AdjustRoute} function to use with process pattern such as {@link Put} that adjust routed FlowFiles based on context. * This function works as a safety net by covering cases that Processor implementation did not use ExceptionHandler and transfer FlowFiles * without considering RollbackOnFailure context. */ public static <FCT extends RollbackOnFailure> AdjustRoute<FCT> createAdjustRoute(Relationship ... failureRelationships) { return (context, session, fc, result) -> { if (fc.isRollbackOnFailure()) { // Check if route contains failure relationship. for (Relationship failureRelationship : failureRelationships) { if (!result.contains(failureRelationship)) { continue; } if (fc.canRollback()) { throw new ProcessException(String.format( "A FlowFile is routed to %s. Rollback session based on context rollbackOnFailure=%s, processedCount=%d, transactional=%s", failureRelationship.getName(), fc.isRollbackOnFailure(), fc.getProcessedCount(), fc.isTransactional())); } else { // Send failed FlowFiles to self. final Map<Relationship, List<FlowFile>> routedFlowFiles = result.getRoutedFlowFiles(); final List<FlowFile> failedFlowFiles = routedFlowFiles.remove(failureRelationship); result.routeTo(failedFlowFiles, Relationship.SELF); } } } }; }
@Override protected void writeRelationships(final Set<Relationship> relationships) throws IOException { writeArray("relationships", relationships,rel -> { writeStartElement("relationship"); writeTextElement("name", rel.getName()); writeTextElement("description", rel.getDescription()); writeBooleanElement("autoTerminated", rel.isAutoTerminated()); writeEndElement(); } ); }
@Test public void testRelationships() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new RouteText()); runner.setProperty(RouteText.MATCH_STRATEGY, RouteText.STARTS_WITH); runner.setProperty(RouteText.ROUTE_STRATEGY, RouteText.ROUTE_TO_MATCHED_WHEN_ANY_PROPERTY_MATCHES); runner.setProperty("simple", "start"); runner.run(); Set<Relationship> relationshipSet = runner.getProcessor().getRelationships(); Set<String> expectedRelationships = new HashSet<>(Arrays.asList("matched", "unmatched", "original")); assertEquals(expectedRelationships.size(), relationshipSet.size()); for (Relationship relationship : relationshipSet) { assertTrue(expectedRelationships.contains(relationship.getName())); } runner.setProperty(RouteText.ROUTE_STRATEGY, RouteText.ROUTE_TO_MATCHING_PROPERTY_NAME); relationshipSet = runner.getProcessor().getRelationships(); expectedRelationships = new HashSet<>(Arrays.asList("simple", "unmatched", "original")); assertEquals(expectedRelationships.size(), relationshipSet.size()); for (Relationship relationship : relationshipSet) { assertTrue(expectedRelationships.contains(relationship.getName())); } runner.run(); }
@Test public void testNotText() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new RouteText()); runner.setProperty(RouteText.MATCH_STRATEGY, RouteText.STARTS_WITH); runner.setProperty("simple", "start"); Set<Relationship> relationshipSet = runner.getProcessor().getRelationships(); Set<String> expectedRelationships = new HashSet<>(Arrays.asList("simple", "unmatched", "original")); assertEquals(expectedRelationships.size(), relationshipSet.size()); for (Relationship relationship : relationshipSet) { assertTrue(expectedRelationships.contains(relationship.getName())); } runner.enqueue(Paths.get("src/test/resources/simple.jpg")); runner.run(); runner.assertTransferCount("unmatched", 1); runner.assertTransferCount("original", 1); final MockFlowFile outOriginal = runner.getFlowFilesForRelationship("original").get(0); outOriginal.assertContentEquals(Paths.get("src/test/resources/simple.jpg")); }