private void processBlockingOperation(boolean supportsConfig, MethodElement operationMethod, OperationDeclarer operation) { operation.blocking(true); operation.withOutputAttributes().ofType(operationMethod.getAttributesMetadataType()); final MetadataType outputType = operationMethod.getReturnMetadataType(); if (isAutoPaging(operationMethod)) { operation.supportsStreaming(true).withOutput().ofType(outputType); addPagedOperationModelProperty(operationMethod, operation, supportsConfig); processPagingTx(operation, operationMethod); } else { operation.withOutput().ofType(outputType); handleByteStreaming(operationMethod, operation, outputType); } }
private void extractOperationExtension(HasOperationDeclarer declarer, ComponentModel operationModel, DirectedGraph<String, DefaultEdge> directedGraph, XmlDslModel xmlDslModel) { String operationName = operationModel.getNameAttribute(); OperationDeclarer operationDeclarer = declarer.withOperation(operationName); ComponentModel bodyComponentModel = operationModel.getInnerComponents() .stream() .filter(child -> child.getIdentifier().equals(OPERATION_BODY_IDENTIFIER)).findFirst() .orElseThrow(() -> new IllegalArgumentException(format("The operation '%s' is missing the <body> statement", operationName))); directedGraph.addVertex(operationName); fillGraphWithTnsReferences(directedGraph, operationName, bodyComponentModel.getInnerComponents()); operationDeclarer.withModelProperty(new OperationComponentModelModelProperty(operationModel, bodyComponentModel)); operationDeclarer.describedAs(getDescription(operationModel)); operationDeclarer.getDeclaration().setDisplayModel(getDisplayModel(operationModel)); extractOperationParameters(operationDeclarer, operationModel); extractOutputType(operationDeclarer.withOutput(), OPERATION_OUTPUT_IDENTIFIER, operationModel, getDeclarationOutputFor(operationName)); extractOutputType(operationDeclarer.withOutputAttributes(), OPERATION_OUTPUT_ATTRIBUTES_IDENTIFIER, operationModel, getDeclarationOutputAttributesFor(operationName)); declareErrorModels(operationDeclarer, xmlDslModel, operationName, operationModel); }
/** * Declares the invoke operation. * * @param configDeclarer the soap config declarer * @param loader a {@link ClassTypeLoader} to load some parameters types. * @param soapErrors the {@link ErrorModel}s that this operation can throw. */ void declare(ConfigurationDeclarer configDeclarer, ClassTypeLoader loader, Set<ErrorModel> soapErrors) { ReflectionCache reflectionCache = new ReflectionCache(); OperationDeclarer operation = configDeclarer.withOperation(OPERATION_NAME) .describedAs(OPERATION_DESCRIPTION) .requiresConnection(true) .blocking(true) .withModelProperty(new ComponentExecutorModelProperty(new SoapOperationExecutorFactory())) .withModelProperty(new ConnectivityModelProperty(ForwardingSoapClient.class)); soapErrors.forEach(operation::withErrorModel); declareMetadata(operation, loader); declareOutput(operation, loader); declareMetadataKeyParameters(operation, loader, reflectionCache); declareRequestParameters(operation, loader); }
private void addPagedOperationModelProperty(MethodElement operationMethod, OperationDeclarer operation, boolean supportsConfig) { checkDefinition(supportsConfig, format("Paged operation '%s' is defined at the extension level but it requires a config, " + "since connections are required for paging", operationMethod.getName())); operation.withModelProperty(new PagedOperationModelProperty()); operation.requiresConnection(true); }
private void declareOutput(OperationDeclarer operation, ClassTypeLoader loader) { operation.withOutput().ofDynamicType(loader.load(SoapOutputPayload.class)); operation.withOutputAttributes().ofType(loader.load(SoapAttributes.class)); }
private void declareRemoveVariable(ExtensionDeclarer extensionDeclarer, ClassTypeLoader typeLoader) { OperationDeclarer removeVariable = extensionDeclarer.withOperation("removeVariable") .describedAs("A processor that remove variables by name or regular expression."); removeVariable.withOutput().ofType(typeLoader.load(void.class)); removeVariable.withOutputAttributes().ofType(typeLoader.load(void.class)); removeVariable.onDefaultParameterGroup() .withOptionalParameter("variableName") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The variable name."); }
scope.withModelProperty(new ExtensionOperationDescriptorModelProperty(scopeMethod)); scope.withModelProperty(new ImplementingMethodModelProperty(method.get())) .withModelProperty(new ComponentExecutorModelProperty(new ReflectiveOperationExecutorFactory<>(declaringClass.get(), method.get()))); new ParameterDeclarationContext(SCOPE, scope.getDeclaration()));
@Before public void before() throws Exception { connectedOperation = spy(new ExtensionDeclarer() .withOperation(CONNECTED_OPERATION) .requiresConnection(true) .getDeclaration()); notConnectedOperation = spy(new ExtensionDeclarer() .withOperation(NOT_CONNECTED_OPERATION) .requiresConnection(false) .getDeclaration()); when(extensionLoadingContext.getExtensionDeclarer()).thenReturn(extensionDeclarer); when(extensionDeclarer.getDeclaration()).thenReturn(extensionDeclaration); when(extensionDeclaration.getOperations()).thenReturn(asList(connectedOperation, notConnectedOperation)); }
private void declareMetadata(OperationDeclarer operation, ClassTypeLoader loader) { ImmutableMap.Builder<String, Supplier<? extends InputTypeResolver>> inputResolver = ImmutableMap.builder(); inputResolver.put(BODY_PARAM, InvokeRequestTypeResolver::new); inputResolver.put(HEADERS_PARAM, InvokeInputHeadersTypeResolver::new); inputResolver.put(ATTACHMENTS_PARAM, InvokeInputAttachmentsTypeResolver::new); DefaultMetadataResolverFactory factory = new DefaultMetadataResolverFactory(InvokeKeysResolver::new, inputResolver.build(), InvokeOutputTypeResolver::new, NullMetadataResolver::new); operation.withModelProperty(new MetadataResolverFactoryModelProperty(() -> factory)); operation.withModelProperty(new MetadataKeyIdModelProperty(loader.load(WebServiceTypeKey.class), KEYS_GROUP, SOAP_INVOKE_METADATA_CATEGORY)); }
private void declareErrorModels(OperationDeclarer operationDeclarer, XmlDslModel xmlDslModel, String operationName, ComponentModel operationModel) { Optional<ComponentModel> optionalParametersComponentModel = operationModel.getInnerComponents() .stream() .filter(child -> child.getIdentifier().equals(OPERATION_ERRORS_IDENTIFIER)).findAny(); optionalParametersComponentModel.ifPresent(componentModel -> componentModel.getInnerComponents() .stream() .filter(child -> child.getIdentifier().equals(OPERATION_ERROR_IDENTIFIER)) .forEach(param -> { final String namespace = xmlDslModel.getPrefix().toUpperCase(); final String typeName = param.getParameters().get(ERROR_TYPE_ATTRIBUTE); if (StringUtils.isBlank(typeName)) { throw new IllegalModelDefinitionException(format("The operation [%s] cannot have an <error> with an empty 'type' attribute", operationName)); } if (typeName.contains(NAMESPACE_SEPARATOR)) { throw new IllegalModelDefinitionException(format("The operation [%s] cannot have an <error> [%s] that contains a reserved character [%s]", operationName, typeName, NAMESPACE_SEPARATOR)); } operationDeclarer.withErrorModel(ErrorModelBuilder.newError(typeName, namespace) .withParent(ErrorModelBuilder.newError(ANY).build()) .build()); })); }
private void declareFlowRef(ExtensionDeclarer extensionDeclarer, ClassTypeLoader typeLoader) { OperationDeclarer flowRef = extensionDeclarer.withOperation("flowRef") .describedAs("Allows a \u0027flow\u0027 to be referenced such that the message processing will continue in the referenced flow " + "before returning. Message processing in the referenced \u0027flow\u0027 will occur within the context of the " + "referenced flow and will therefore use its exception strategy etc.") .withErrorModel(routingError); flowRef.withOutput().ofType(BaseTypeBuilder.create(JAVA).anyType().build()); flowRef.withOutputAttributes().ofType(BaseTypeBuilder.create(JAVA).anyType().build()); flowRef.onDefaultParameterGroup() .withRequiredParameter("name") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The name of the flow to call"); }
operationDeclarer.withModelProperty(new ExtensionOperationDescriptorModelProperty(operationMethod)); .withModelProperty(new ImplementingMethodModelProperty(method.get())) .withModelProperty(new ComponentExecutorModelProperty(new ReflectiveOperationExecutorFactory<>(declaringClass.get(), method.get()))); operationDeclarer.getDeclaration()); processMimeType(operationDeclarer, operationMethod); declareParameters(operationDeclarer, operationMethod.getParameters(), fieldParameters, declarationContext);
private void addPagedOperationModelProperty(MethodElement operationMethod, OperationDeclarer operation, boolean supportsConfig) { checkDefinition(supportsConfig, format("Paged operation '%s' is defined at the extension level but it requires a config, " + "since connections are required for paging", operationMethod.getName())); operation.withModelProperty(new PagedOperationModelProperty()); operation.requiresConnection(true); }
private void declareRaiseError(ExtensionDeclarer extensionDeclarer, ClassTypeLoader typeLoader) { OperationDeclarer raiseError = extensionDeclarer.withOperation("raiseError") .describedAs("Throws an error with the specified type and description."); raiseError.withOutput().ofType(typeLoader.load(void.class)); raiseError.withOutputAttributes().ofType(typeLoader.load(void.class)); raiseError.onDefaultParameterGroup() .withRequiredParameter("type") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The error type to raise."); raiseError.onDefaultParameterGroup() .withOptionalParameter("description") .ofType(typeLoader.load(String.class)) .describedAs("The description of this error."); }
operation.withOutput().ofType(genericTypes.get(0)); operation.withOutputAttributes().ofType(genericTypes.get(1)); operation.blocking(false); operation.supportsStreaming(false);
scope.withModelProperty(new ExtensionOperationDescriptorModelProperty(scopeMethod)); scope.withModelProperty(new ImplementingMethodModelProperty(method.get())) .withModelProperty(new ComponentExecutorModelProperty(new ReflectiveOperationExecutorFactory<>(declaringClass.get(), method.get()))); new ParameterDeclarationContext(SCOPE, scope.getDeclaration()));
private void declareParseTemplate(ExtensionDeclarer extensionDeclarer, ClassTypeLoader typeLoader) { OperationDeclarer parseTemplate = extensionDeclarer.withOperation("parseTemplate") .describedAs("A transformer that parses a template defined inline."); parseTemplate.withOutput().ofType(typeLoader.load(String.class)); parseTemplate.withOutputAttributes().ofType(typeLoader.load(void.class)); parseTemplate.onDefaultParameterGroup() .withOptionalParameter("content") .ofType(typeLoader.load(String.class)) .withRole(ParameterRole.PRIMARY_CONTENT) .withExpressionSupport(SUPPORTED) .describedAs("Template to be processed."); parseTemplate.onDefaultParameterGroup() .withOptionalParameter("location") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The location of the template. The order in which the transformer will attempt to load the file are: from the file system, from a URL or from the classpath."); }
private void processBlockingOperation(boolean supportsConfig, MethodElement operationMethod, OperationDeclarer operation) { operation.blocking(true); operation.withOutputAttributes().ofType(operationMethod.getAttributesMetadataType()); final MetadataType outputType = operationMethod.getReturnMetadataType(); if (isAutoPaging(operationMethod)) { operation.supportsStreaming(true).withOutput().ofType(outputType); addPagedOperationModelProperty(operationMethod, operation, supportsConfig); processPagingTx(operation, operationMethod); } else { operation.withOutput().ofType(outputType); handleByteStreaming(operationMethod, operation, outputType); } }
operationDeclarer.withModelProperty(new ExtensionOperationDescriptorModelProperty(operationMethod)); .withModelProperty(new ImplementingMethodModelProperty(method.get())) .withModelProperty(new ComponentExecutorModelProperty(new ReflectiveOperationExecutorFactory<>(declaringClass.get(), method.get()))); operationDeclarer.getDeclaration()); processMimeType(operationDeclarer, operationMethod); declareParameters(operationDeclarer, operationMethod.getParameters(), fieldParameters, declarationContext);
private void declareSetPayload(ExtensionDeclarer extensionDeclarer, ClassTypeLoader typeLoader) { OperationDeclarer setPayload = extensionDeclarer.withOperation("setPayload") .describedAs("A transformer that sets the payload with the provided value."); setPayload.withOutput().ofType(typeLoader.load(void.class)); setPayload.withOutputAttributes().ofType(typeLoader.load(void.class)); setPayload.onDefaultParameterGroup() .withOptionalParameter("encoding") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The encoding of the value assigned to the payload."); setPayload.onDefaultParameterGroup() .withRequiredParameter("value") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The value to be set on the payload. Supports expressions."); setPayload.onDefaultParameterGroup() .withOptionalParameter("mimeType") .ofType(typeLoader.load(String.class)) .withExpressionSupport(NOT_SUPPORTED) .describedAs("The mime type, e.g. text/plain or application/json"); }