@Override public void verifyCanStart(final Set<ControllerServiceNode> ignoredReferences) { switch (getScheduledState()) { case DISABLED: throw new IllegalStateException(this + " cannot be started because it is disabled"); case RUNNING: throw new IllegalStateException(this + " cannot be started because it is already running"); case STOPPED: break; } final int activeThreadCount = getActiveThreadCount(); if (activeThreadCount > 0) { throw new IllegalStateException( this + " cannot be started because it has " + activeThreadCount + " active threads already"); } final Set<String> ids = new HashSet<>(); for (final ControllerServiceNode node : ignoredReferences) { ids.add(node.getIdentifier()); } final Collection<ValidationResult> validationResults = getValidationErrors(ids); for (final ValidationResult result : validationResults) { if (!result.isValid()) { throw new IllegalStateException( this + " cannot be started because it is not valid: " + result); } } }
@Override public boolean isValid() { readLock.lock(); try { final ValidationContext validationContext = validationContextFactory.newValidationContext(getProperties(), getAnnotationData()); final Collection<ValidationResult> validationResults; try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) { validationResults = getProcessor().validate(validationContext); } for (final ValidationResult result : validationResults) { if (!result.isValid()) { return false; } } for (final Relationship undef : getUndefinedRelationships()) { if (!isAutoTerminated(undef)) { return false; } } switch (getInputRequirement()) { case INPUT_ALLOWED: break; case INPUT_FORBIDDEN: { if (!getIncomingNonLoopConnections().isEmpty()) { return false; } break; } case INPUT_REQUIRED: { if (getIncomingNonLoopConnections().isEmpty()) { return false; } break; } } } catch (final Throwable t) { return false; } finally { readLock.unlock(); } return true; }
@Override public void assertValid(final ControllerService service) { final StateManager serviceStateManager = controllerServiceStateManagers.get(service.getIdentifier()); if (serviceStateManager == null) { throw new IllegalStateException( "Controller Service has not been added to this TestRunner via the #addControllerService method"); } final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager) .getControllerServiceValidationContext(service); final Collection<ValidationResult> results = context.getControllerService(service.getIdentifier()).validate(validationContext); for (final ValidationResult result : results) { if (!result.isValid()) { Assert.fail( "Expected Controller Service to be valid but it is invalid due to: " + result.toString()); } } }
@Override public Collection<ValidationResult> getValidationErrors() { final List<ValidationResult> results = new ArrayList<>(); readLock.lock(); try { final ValidationContext validationContext = validationContextFactory.newValidationContext(getProperties(), getAnnotationData()); final Collection<ValidationResult> validationResults; try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) { validationResults = getProcessor().validate(validationContext); } for (final ValidationResult result : validationResults) { if (!result.isValid()) { results.add(result); } } for (final Relationship relationship : getUndefinedRelationships()) { if (!isAutoTerminated(relationship)) { final ValidationResult error = new ValidationResult.Builder() .explanation( "Relationship '" + relationship.getName() + "' is not connected to any component and is not auto-terminated") .subject("Relationship " + relationship.getName()) .valid(false) .build(); results.add(error); } } switch (getInputRequirement()) { case INPUT_ALLOWED: break; case INPUT_FORBIDDEN: { final int incomingConnCount = getIncomingNonLoopConnections().size(); if (incomingConnCount != 0) { results.add( new ValidationResult.Builder() .explanation( "Processor does not allow upstream connections but currently has " + incomingConnCount) .subject("Upstream Connections") .valid(false) .build()); } break; } case INPUT_REQUIRED: { if (getIncomingNonLoopConnections().isEmpty()) { results.add( new ValidationResult.Builder() .explanation( "Processor requires an upstream connection but currently has none") .subject("Upstream Connections") .valid(false) .build()); } break; } } } catch (final Throwable t) { results.add( new ValidationResult.Builder() .explanation("Failed to run validation due to " + t.toString()) .valid(false) .build()); } finally { readLock.unlock(); } return results; }