/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.module.extension.internal; import static java.util.stream.Collectors.toList; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.junit.Assert.assertThat; import static org.mule.runtime.api.meta.Category.COMMUNITY; import static org.mule.runtime.api.meta.ExpressionSupport.NOT_SUPPORTED; import static org.mule.runtime.api.meta.ExpressionSupport.REQUIRED; import static org.mule.runtime.api.meta.ExpressionSupport.SUPPORTED; import static org.mule.runtime.api.meta.model.ExecutionType.BLOCKING; import static org.mule.runtime.api.meta.model.ExecutionType.CPU_INTENSIVE; import static org.mule.runtime.api.meta.model.ExecutionType.CPU_LITE; import static org.mule.runtime.api.meta.model.error.ErrorModelBuilder.newError; import static org.mule.runtime.api.meta.model.parameter.ParameterRole.BEHAVIOUR; import static org.mule.runtime.api.meta.model.parameter.ParameterRole.CONTENT; import static org.mule.runtime.core.config.MuleManifest.getProductDescription; import static org.mule.runtime.core.config.MuleManifest.getProductName; import static org.mule.runtime.core.config.MuleManifest.getProductVersion; import static org.mule.runtime.core.config.MuleManifest.getVendorName; import static org.mule.runtime.internal.dsl.DslConstants.CORE_PREFIX; import static org.mule.runtime.module.extension.internal.resources.MuleExtensionModelProvider.getMuleExtensionModel; import org.mule.metadata.api.annotation.EnumAnnotation; import org.mule.metadata.api.annotation.TypeIdAnnotation; import org.mule.metadata.api.model.ArrayType; import org.mule.metadata.api.model.MetadataType; import org.mule.metadata.api.model.ObjectType; import org.mule.metadata.api.model.StringType; import org.mule.metadata.api.model.UnionType; import org.mule.metadata.api.model.impl.DefaultAnyType; import org.mule.metadata.api.model.impl.DefaultArrayType; import org.mule.metadata.api.model.impl.DefaultBooleanType; import org.mule.metadata.api.model.impl.DefaultNumberType; import org.mule.metadata.api.model.impl.DefaultObjectType; import org.mule.metadata.api.model.impl.DefaultStringType; import org.mule.metadata.api.model.impl.DefaultVoidType; import org.mule.metadata.api.utils.MetadataTypeUtils; import org.mule.runtime.api.message.Attributes; import org.mule.runtime.api.message.NullAttributes; import org.mule.runtime.api.meta.ExpressionSupport; import org.mule.runtime.api.meta.MuleVersion; import org.mule.runtime.api.meta.model.ExtensionModel; import org.mule.runtime.api.meta.model.error.ErrorModel; import org.mule.runtime.api.meta.model.operation.OperationModel; import org.mule.runtime.api.meta.model.operation.RouteModel; import org.mule.runtime.api.meta.model.operation.RouterModel; import org.mule.runtime.api.meta.model.operation.ScopeModel; import org.mule.runtime.api.meta.model.parameter.ParameterGroupModel; import org.mule.runtime.api.meta.model.parameter.ParameterModel; import org.mule.runtime.api.meta.model.source.SourceModel; import org.mule.runtime.core.api.processor.LoggerMessageProcessor; import org.mule.runtime.core.api.processor.LoggerMessageProcessor.LogLevel; import org.mule.runtime.api.store.ObjectStore; import org.mule.runtime.core.api.transformer.Transformer; import org.mule.runtime.core.routing.AggregationStrategy; import org.mule.runtime.core.source.scheduler.schedule.FixedFrequencyScheduler; import org.mule.tck.junit4.AbstractMuleContextTestCase; import java.util.List; import java.util.Optional; import org.junit.Test; public class CoreExtensionModelTestCase extends AbstractMuleContextTestCase { private static final ErrorModel errorMuleAny = newError("ANY", "MULE").build(); private static ExtensionModel coreExtensionModel = getMuleExtensionModel(); @Test public void consistentWithManifest() { assertThat(coreExtensionModel.getName(), is(getProductName())); assertThat(coreExtensionModel.getDescription(), is(getProductDescription() + ": Core components")); assertThat(coreExtensionModel.getVersion(), is(getProductVersion())); assertThat(coreExtensionModel.getVendor(), is(getVendorName())); assertThat(coreExtensionModel.getCategory(), is(COMMUNITY)); assertThat(coreExtensionModel.getMinMuleVersion(), is(new MuleVersion(getProductVersion()))); } @Test public void consistentWithSchema() { assertThat(coreExtensionModel.getXmlDslModel().getPrefix(), is(CORE_PREFIX)); assertThat(coreExtensionModel.getXmlDslModel().getNamespace(), is("http://www.mulesoft.org/schema/mule/core")); assertThat(coreExtensionModel.getXmlDslModel().getSchemaLocation(), is("http://www.mulesoft.org/schema/mule/core/current/mule.xsd")); assertThat(coreExtensionModel.getXmlDslModel().getSchemaVersion(), is(getProductVersion())); assertThat(coreExtensionModel.getXmlDslModel().getXsdFileName(), is("mule.xsd")); } @Test public void otherModels() { assertThat(coreExtensionModel.getResources(), empty()); assertThat(coreExtensionModel.getSubTypes(), empty()); assertThat(coreExtensionModel.getExternalLibraryModels(), empty()); assertThat(coreExtensionModel.getImportedTypes(), empty()); assertThat(coreExtensionModel.getConfigurationModels(), empty()); assertThat(coreExtensionModel.getOperationModels(), hasSize(16)); assertThat(coreExtensionModel.getConnectionProviders(), empty()); assertThat(coreExtensionModel.getErrorModels(), hasItem(newError("TRANSFORMATION", "CORE") .withParent(newError("TRANSFORMATION", "MULE").withParent(errorMuleAny).build()).build())); assertThat(coreExtensionModel.getErrorModels(), hasItem(newError("CORRELATION_TIMEOUT", "CORE") .withParent(newError("ANY", "CORE").withParent(errorMuleAny).build()).build())); assertThat(coreExtensionModel.getSourceModels(), hasSize(1)); assertThat(coreExtensionModel.getModelProperties(), empty()); assertThat(coreExtensionModel.getTypes(), empty()); } // TODO MULE-9139 update this source model @Test public void poll() { final SourceModel pollModel = coreExtensionModel.getSourceModel("poll").get(); assertThat(pollModel.getErrorModels(), empty()); assertThat(pollModel.hasResponse(), is(false)); assertThat(pollModel.getOutput().getType(), instanceOf(DefaultObjectType.class)); assertThat(pollModel.getOutput().hasDynamicType(), is(true)); assertThat(pollModel.getOutputAttributes().getType(), instanceOf(DefaultObjectType.class)); assertThat(pollModel.getOutputAttributes().hasDynamicType(), is(false)); final List<ParameterModel> paramModels = pollModel.getAllParameterModels(); assertThat(paramModels, hasSize(1)); assertThat(paramModels.get(0).getName(), is("fixedFrequencyScheduler")); assertThat(paramModels.get(0).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(0).getType(), instanceOf(DefaultObjectType.class)); assertThat(paramModels.get(0).isRequired(), is(false)); assertThat(paramModels.get(0).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(FixedFrequencyScheduler.class.getName())); final DefaultObjectType ffSchedulerType = (DefaultObjectType) paramModels.get(0).getType(); assertThat(ffSchedulerType.getFields(), hasSize(3)); assertThat(ffSchedulerType.getFieldByName("frequency").get().isRequired(), is(false)); assertThat(ffSchedulerType.getFieldByName("frequency").get().getValue(), instanceOf(DefaultNumberType.class)); assertThat(ffSchedulerType.getFieldByName("startDelay").get().isRequired(), is(false)); assertThat(ffSchedulerType.getFieldByName("startDelay").get().getValue(), instanceOf(DefaultNumberType.class)); assertThat(ffSchedulerType.getFieldByName("timeUnit").get().isRequired(), is(false)); assertThat(ffSchedulerType.getFieldByName("timeUnit").get().getValue(), instanceOf(DefaultStringType.class)); // TODO add the route } @Test public void logger() { final OperationModel loggerModel = coreExtensionModel.getOperationModel("logger").get(); assertThat(loggerModel.getErrorModels(), empty()); assertThat(loggerModel.getExecutionType(), is(CPU_LITE)); assertOutputSameAsInput(loggerModel); final List<ParameterModel> paramModels = loggerModel.getAllParameterModels(); assertThat(paramModels, hasSize(3)); assertThat(paramModels.get(0).getName(), is("message")); assertThat(paramModels.get(0).getExpressionSupport(), is(SUPPORTED)); assertThat(paramModels.get(0).getType(), instanceOf(DefaultStringType.class)); assertThat(paramModels.get(0).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(String.class.getName())); assertThat(paramModels.get(0).isRequired(), is(false)); assertThat(paramModels.get(1).getName(), is("category")); assertThat(paramModels.get(1).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(1).getType(), instanceOf(DefaultStringType.class)); assertThat(paramModels.get(1).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(String.class.getName())); assertThat(paramModels.get(1).isRequired(), is(false)); assertThat(paramModels.get(2).getName(), is("level")); assertThat(paramModels.get(2).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(2).getType(), instanceOf(DefaultStringType.class)); assertThat(paramModels.get(2).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(LoggerMessageProcessor.class.getName() + "." + LogLevel.class.getSimpleName())); assertThat(paramModels.get(2).isRequired(), is(false)); } @Test public void transform() { final OperationModel transformModel = coreExtensionModel.getOperationModel("transform").get(); assertThat(transformModel.getErrorModels(), hasItem(newError("TRANSFORMATION", "CORE") .withParent(newError("TRANSFORMATION", "MULE").withParent(errorMuleAny).build()).build())); assertThat(transformModel.getExecutionType(), is(CPU_INTENSIVE)); // TODO MULE-11935 a way is needed to determine the return type of the trasformer in the extension model. assertComponentDeterminesOutput(transformModel); final List<ParameterGroupModel> paramGroupModels = transformModel.getParameterGroupModels(); assertThat(transformModel.getAllParameterModels(), hasSize(6)); assertThat(paramGroupModels, hasSize(3)); assertThat(paramGroupModels.get(0).getName(), is("General")); List<ParameterModel> paramModels = paramGroupModels.get(0).getParameterModels(); assertThat(paramModels.get(0).getName(), is("ref")); assertThat(paramModels.get(0).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(0).getType(), instanceOf(DefaultObjectType.class)); assertThat(paramModels.get(0).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(Transformer.class.getName())); assertThat(paramModels.get(0).isRequired(), is(true)); assertThat(paramModels.get(1).getName(), is("SetVariables")); assertThat(paramModels.get(1).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(1).getType(), instanceOf(DefaultArrayType.class)); assertThat(paramModels.get(1).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(List.class.getName())); assertThat(paramModels.get(1).isRequired(), is(false)); assertThat(((ArrayType) paramModels.get(1).getType()).getType(), instanceOf(ObjectType.class)); assertThat(((ObjectType) ((ArrayType) paramModels.get(1).getType()).getType()).getFields(), hasSize(3)); assertThat(((ObjectType) ((ArrayType) paramModels.get(1).getType()).getType()).getFields().stream() .map(MetadataTypeUtils::getLocalPart).collect(toList()), containsInAnyOrder("variableName", "resource", "script")); assertThat(paramGroupModels.get(1).getName(), is("SetPayload")); assertScriptAndResource(paramGroupModels.get(1).getParameterModels()); assertThat(paramGroupModels.get(2).getName(), is("SetAttributes")); assertScriptAndResource(paramGroupModels.get(2).getParameterModels()); } private void assertScriptAndResource(List<ParameterModel> paramModels) { assertThat(paramModels.get(0).getName(), is("script")); assertThat(paramModels.get(0).getExpressionSupport(), is(REQUIRED)); assertThat(paramModels.get(0).getType(), instanceOf(DefaultObjectType.class)); assertThat(paramModels.get(0).isRequired(), is(false)); assertThat(paramModels.get(0).getRole(), is(CONTENT)); assertThat(paramModels.get(1).getName(), is("resource")); assertThat(paramModels.get(1).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(1).getType(), instanceOf(StringType.class)); assertThat(paramModels.get(1).isRequired(), is(false)); assertThat(paramModels.get(1).getRole(), is(BEHAVIOUR)); } @Test public void splitter() { final OperationModel splitterModel = coreExtensionModel.getOperationModel("splitter").get(); assertThat(splitterModel.getErrorModels(), empty()); assertThat(splitterModel.getExecutionType(), is(CPU_INTENSIVE)); assertComponentDeterminesOutput(splitterModel); assertThat(splitterModel.getAllParameterModels(), hasSize(2)); assertMultiPayload(splitterModel.getAllParameterModels().get(0), "payload", REQUIRED); assertTarget(splitterModel.getAllParameterModels().get(1)); } @Test public void collectionSplitter() { final OperationModel collectionSplitterModel = coreExtensionModel.getOperationModel("collectionSplitter").get(); assertThat(collectionSplitterModel.getErrorModels(), empty()); assertThat(collectionSplitterModel.getExecutionType(), is(CPU_LITE)); assertComponentDeterminesOutput(collectionSplitterModel); assertThat(collectionSplitterModel.getAllParameterModels(), hasSize(2)); assertMultiPayload(collectionSplitterModel.getAllParameterModels().get(0), "payload", SUPPORTED); assertTarget(collectionSplitterModel.getAllParameterModels().get(1)); } @Test public void collectionAggregator() { final OperationModel collectionAggregatorModel = coreExtensionModel.getOperationModel("collection-aggregator").get(); assertThat(collectionAggregatorModel.getErrorModels(), hasItem(newError("CORRELATION_TIMEOUT", "CORE") .withParent(newError("ANY", "CORE").withParent(errorMuleAny).build()).build())); assertThat(collectionAggregatorModel.getExecutionType(), is(BLOCKING)); assertThat(collectionAggregatorModel.getOutput().getType(), instanceOf(DefaultArrayType.class)); assertThat(collectionAggregatorModel.getOutput().hasDynamicType(), is(false)); assertThat(collectionAggregatorModel.getOutputAttributes().getType(), instanceOf(DefaultObjectType.class)); assertThat(collectionAggregatorModel.getOutputAttributes().getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(NullAttributes.class.getName())); assertThat(collectionAggregatorModel.getOutputAttributes().hasDynamicType(), is(false)); final List<ParameterModel> paramModels = collectionAggregatorModel.getAllParameterModels(); assertThat(paramModels, hasSize(8)); assertThat(paramModels.get(0).getName(), is("timeout")); assertThat(paramModels.get(0).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(0).getType(), instanceOf(DefaultNumberType.class)); assertThat(paramModels.get(0).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(long.class.getName())); assertThat(paramModels.get(0).isRequired(), is(true)); assertThat(paramModels.get(1).getName(), is("failOnTimeout")); assertThat(paramModels.get(1).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(1).getType(), instanceOf(DefaultBooleanType.class)); assertThat(paramModels.get(1).isRequired(), is(false)); assertThat(paramModels.get(2).getName(), is("processedGroupsObjectStore")); assertThat(paramModels.get(2).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(2).getType(), instanceOf(DefaultObjectType.class)); assertThat(paramModels.get(2).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(ObjectStore.class.getName())); assertThat(paramModels.get(2).isRequired(), is(false)); assertThat(paramModels.get(3).getName(), is("eventGroupsObjectStore")); assertThat(paramModels.get(3).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(3).getType(), instanceOf(DefaultObjectType.class)); assertThat(paramModels.get(3).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(ObjectStore.class.getName())); assertThat(paramModels.get(3).isRequired(), is(false)); assertThat(paramModels.get(4).getName(), is("persistentStores")); assertThat(paramModels.get(4).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(4).getType(), instanceOf(DefaultBooleanType.class)); assertThat(paramModels.get(4).isRequired(), is(false)); assertThat(paramModels.get(5).getName(), is("storePrefix")); assertThat(paramModels.get(5).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(paramModels.get(5).getType(), instanceOf(DefaultStringType.class)); assertThat(paramModels.get(5).isRequired(), is(true)); assertPayload(paramModels.get(6)); assertTarget(paramModels.get(7)); } @Test public void foreach() { final ScopeModel foreachModel = (ScopeModel) coreExtensionModel.getOperationModel("foreach").get(); assertThat(foreachModel.getErrorModels(), empty()); assertThat(foreachModel.getExecutionType(), is(CPU_LITE)); assertComponentDeterminesOutput(foreachModel); assertThat(foreachModel.getAllParameterModels(), hasSize(5)); assertMultiPayload(foreachModel.getAllParameterModels().get(0), "collection", SUPPORTED); assertThat(foreachModel.getAllParameterModels().get(1).getName(), is("batchSize")); assertThat(foreachModel.getAllParameterModels().get(1).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(foreachModel.getAllParameterModels().get(1).getType(), instanceOf(DefaultNumberType.class)); assertThat(foreachModel.getAllParameterModels().get(1).isRequired(), is(false)); assertThat(foreachModel.getAllParameterModels().get(2).getName(), is("rootMessageVariableName")); assertThat(foreachModel.getAllParameterModels().get(2).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(foreachModel.getAllParameterModels().get(2).getType(), instanceOf(DefaultStringType.class)); assertThat(foreachModel.getAllParameterModels().get(2).isRequired(), is(false)); assertThat(foreachModel.getAllParameterModels().get(3).getName(), is("counterVariableName")); assertThat(foreachModel.getAllParameterModels().get(3).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(foreachModel.getAllParameterModels().get(3).getType(), instanceOf(DefaultStringType.class)); assertThat(foreachModel.getAllParameterModels().get(3).isRequired(), is(false)); assertTarget(foreachModel.getAllParameterModels().get(4)); } @Test public void flowRef() { final OperationModel flowRefModel = coreExtensionModel.getOperationModel("flow-ref").get(); assertAssociatedProcessorsChangeOutput(flowRefModel); assertThat(flowRefModel.getAllParameterModels(), hasSize(3)); assertThat(flowRefModel.getAllParameterModels().get(0).getName(), is("name")); assertThat(flowRefModel.getAllParameterModels().get(0).getExpressionSupport(), is(SUPPORTED)); assertThat(flowRefModel.getAllParameterModels().get(0).getType(), instanceOf(DefaultStringType.class)); assertThat(flowRefModel.getAllParameterModels().get(0).isRequired(), is(true)); assertPayload(flowRefModel.getAllParameterModels().get(1)); assertTarget(flowRefModel.getAllParameterModels().get(2)); } @Test public void filter() { final OperationModel filterModel = coreExtensionModel.getOperationModel("filter").get(); assertOutputSameAsInput(filterModel); assertThat(filterModel.getAllParameterModels(), hasSize(2)); assertPayload(filterModel.getAllParameterModels().get(1)); } @Test public void idempotentMessageValidator() { final OperationModel filterModel = coreExtensionModel.getOperationModel("idempotentMessageValidator").get(); assertOutputSameAsInput(filterModel); assertThat(filterModel.getAllParameterModels(), hasSize(4)); assertThat(filterModel.getAllParameterModels().get(0).getName(), is("idExpression")); assertThat(filterModel.getAllParameterModels().get(0).getExpressionSupport(), is(SUPPORTED)); assertThat(filterModel.getAllParameterModels().get(0).getType(), instanceOf(DefaultObjectType.class)); assertThat(filterModel.getAllParameterModels().get(0).isRequired(), is(false)); assertThat(filterModel.getAllParameterModels().get(1).getName(), is("valueExpression")); assertThat(filterModel.getAllParameterModels().get(1).getExpressionSupport(), is(SUPPORTED)); assertThat(filterModel.getAllParameterModels().get(1).getType(), instanceOf(DefaultStringType.class)); assertThat(filterModel.getAllParameterModels().get(1).isRequired(), is(false)); assertThat(filterModel.getAllParameterModels().get(2).getName(), is("objectStore")); assertThat(filterModel.getAllParameterModels().get(2).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(filterModel.getAllParameterModels().get(2).getType(), instanceOf(DefaultObjectType.class)); assertThat(filterModel.getAllParameterModels().get(2).isRequired(), is(false)); assertThat(filterModel.getAllParameterModels().get(3).getName(), is("storePrefix")); assertThat(filterModel.getAllParameterModels().get(3).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(filterModel.getAllParameterModels().get(3).getType(), instanceOf(DefaultStringType.class)); assertThat(filterModel.getAllParameterModels().get(3).isRequired(), is(false)); } @Test public void choice() { final RouterModel choiceModel = (RouterModel) coreExtensionModel.getOperationModel("choice").get(); assertThat(choiceModel.getErrorModels(), empty()); assertThat(choiceModel.getExecutionType(), is(CPU_LITE)); assertAssociatedProcessorsChangeOutput(choiceModel); assertThat(choiceModel.getAllParameterModels(), empty()); assertThat(choiceModel.getRouteModels(), hasSize(2)); final RouteModel whenRouteModel = choiceModel.getRouteModels().get(0); assertThat(whenRouteModel.getName(), is("when")); assertThat(whenRouteModel.getMinOccurs(), is(1)); assertThat(whenRouteModel.getMaxOccurs(), is(Optional.empty())); assertThat(whenRouteModel.getAllParameterModels(), hasSize(1)); assertThat(whenRouteModel.getAllParameterModels().get(0).getName(), is("expression")); assertThat(whenRouteModel.getAllParameterModels().get(0).getExpressionSupport(), is(SUPPORTED)); assertThat(whenRouteModel.getAllParameterModels().get(0).getType(), instanceOf(DefaultBooleanType.class)); assertThat(whenRouteModel.getAllParameterModels().get(0).isRequired(), is(false)); final RouteModel otherwiseRouteModel = choiceModel.getRouteModels().get(1); assertThat(otherwiseRouteModel.getName(), is("otherwise")); assertThat(otherwiseRouteModel.getMinOccurs(), is(0)); assertThat(otherwiseRouteModel.getMaxOccurs().get(), is(1)); assertThat(otherwiseRouteModel.getAllParameterModels(), empty()); } @Test public void scatterGather() { final RouterModel scatterGatherModel = (RouterModel) coreExtensionModel.getOperationModel("scatter-gather").get(); assertThat(scatterGatherModel.getErrorModels(), empty()); assertThat(scatterGatherModel.getExecutionType(), is(CPU_LITE)); assertComponentDeterminesOutput(scatterGatherModel); assertThat(scatterGatherModel.getAllParameterModels(), hasSize(3)); assertThat(scatterGatherModel.getAllParameterModels().get(0).getName(), is("parallel")); assertThat(scatterGatherModel.getAllParameterModels().get(0).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(scatterGatherModel.getAllParameterModels().get(0).getType(), instanceOf(DefaultBooleanType.class)); assertThat(scatterGatherModel.getAllParameterModels().get(0).isRequired(), is(false)); assertThat(scatterGatherModel.getAllParameterModels().get(1).getName(), is("timeout")); assertThat(scatterGatherModel.getAllParameterModels().get(1).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(scatterGatherModel.getAllParameterModels().get(1).getType(), instanceOf(DefaultNumberType.class)); assertThat(scatterGatherModel.getAllParameterModels().get(1).isRequired(), is(false)); assertThat(scatterGatherModel.getAllParameterModels().get(2).getName(), is("custom-aggregation-strategy")); assertThat(scatterGatherModel.getAllParameterModels().get(2).getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(scatterGatherModel.getAllParameterModels().get(2).getType(), instanceOf(DefaultObjectType.class)); assertThat(scatterGatherModel.getAllParameterModels().get(2).getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(AggregationStrategy.class.getName())); assertThat(scatterGatherModel.getAllParameterModels().get(2).isRequired(), is(false)); assertThat(scatterGatherModel.getRouteModels(), hasSize(1)); final RouteModel routeModel = scatterGatherModel.getRouteModels().get(0); assertThat(routeModel.getName(), is("route")); assertThat(routeModel.getMinOccurs(), is(2)); assertThat(routeModel.getMaxOccurs(), is(Optional.empty())); assertThat(routeModel.getAllParameterModels(), empty()); } @Test public void async() { final ScopeModel asyncModel = (ScopeModel) coreExtensionModel.getOperationModel("async").get(); assertThat(asyncModel.getErrorModels(), empty()); assertThat(asyncModel.getExecutionType(), is(CPU_LITE)); assertOutputSameAsInput(asyncModel); assertThat(asyncModel.getAllParameterModels(), hasSize(0)); } @Test public void tryScope() { final ScopeModel tryModel = (ScopeModel) coreExtensionModel.getOperationModel("try").get(); assertThat(tryModel.getErrorModels(), empty()); assertThat(tryModel.getExecutionType(), is(BLOCKING)); assertAssociatedProcessorsChangeOutput(tryModel); List<ParameterModel> allParameterModels = tryModel.getAllParameterModels(); assertThat(allParameterModels, hasSize(2)); ParameterModel action = allParameterModels.get(0); assertThat(action.getName(), is("transactionalAction")); assertThat(action.getType(), is(instanceOf(DefaultStringType.class))); assertThat(action.getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(action.isRequired(), is(false)); ParameterModel type = allParameterModels.get(1); assertThat(type.getName(), is("transactionType")); assertThat(type.getType(), is(instanceOf(DefaultStringType.class))); assertThat(type.getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(type.isRequired(), is(false)); } // TODO: MULE-12224 - Provide support for scope as top level elements @Test public void errorHandler() { final ScopeModel errorHandlerModel = (ScopeModel) coreExtensionModel.getOperationModel("error-handler").get(); assertThat(errorHandlerModel.getErrorModels(), empty()); assertThat(errorHandlerModel.getExecutionType(), is(CPU_LITE)); assertAssociatedProcessorsChangeOutput(errorHandlerModel); List<ParameterModel> allParameterModels = errorHandlerModel.getAllParameterModels(); assertThat(allParameterModels, hasSize(0)); } @Test public void onErrorContinue() { verifyOnError("on-error-continue"); } @Test public void onErrorPropagate() { verifyOnError("on-error-propagate"); } // TODO: MULE-12265 - Provide support for "exclusive scopes" void verifyOnError(String name) { final ScopeModel continueModel = (ScopeModel) coreExtensionModel.getOperationModel(name).get(); assertThat(continueModel.getErrorModels(), empty()); assertThat(continueModel.getExecutionType(), is(CPU_LITE)); assertAssociatedProcessorsChangeOutput(continueModel); List<ParameterModel> allParameterModels = continueModel.getAllParameterModels(); assertThat(allParameterModels, hasSize(4)); ParameterModel type = allParameterModels.get(0); assertThat(type.getName(), is("type")); assertThat(type.getType(), is(instanceOf(UnionType.class))); List<MetadataType> types = ((UnionType) type.getType()).getTypes(); assertThat(types, hasSize(2)); assertThat(types.get(0), is(instanceOf(DefaultStringType.class))); assertThat(types.get(1), is(instanceOf(DefaultStringType.class))); assertThat(types.get(1).getAnnotation(EnumAnnotation.class).get().getValues(), arrayContainingInAnyOrder( "ANY", "REDELIVERY_EXHAUSTED", "TRANSFORMATION", "EXPRESSION", "SECURITY", "ROUTING", "CONNECTIVITY", "RETRY_EXHAUSTED")); assertThat(type.getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(type.isRequired(), is(false)); ParameterModel when = allParameterModels.get(1); assertThat(when.getName(), is("when")); assertThat(when.getType(), is(instanceOf(DefaultStringType.class))); assertThat(when.getExpressionSupport(), is(SUPPORTED)); assertThat(when.isRequired(), is(false)); ParameterModel log = allParameterModels.get(2); assertThat(log.getName(), is("logException")); assertThat(log.getType(), is(instanceOf(DefaultBooleanType.class))); assertThat(log.getExpressionSupport(), is(SUPPORTED)); assertThat(log.isRequired(), is(false)); ParameterModel notifications = allParameterModels.get(3); assertThat(notifications.getName(), is("enableNotifications")); assertThat(notifications.getType(), is(instanceOf(DefaultBooleanType.class))); assertThat(notifications.getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(notifications.isRequired(), is(false)); assertThat(notifications.getDefaultValue(), is("true")); } /** * The operation returns its input as the output. * * @param model the model to assert on */ private void assertOutputSameAsInput(final OperationModel model) { assertThat(model.getOutput().getType(), instanceOf(DefaultVoidType.class)); assertThat(model.getOutput().hasDynamicType(), is(false)); assertThat(model.getOutputAttributes().getType(), instanceOf(DefaultVoidType.class)); assertThat(model.getOutputAttributes().hasDynamicType(), is(false)); } /** * The operation buids its own output, leaving the resulting message without attrbiutes. * * @param model the model to assert on */ private void assertComponentDeterminesOutput(final OperationModel model) { assertThat(model.getOutput().getType(), instanceOf(DefaultAnyType.class)); assertThat(model.getOutput().hasDynamicType(), is(false)); assertThat(model.getOutputAttributes().getType(), instanceOf(DefaultObjectType.class)); assertThat(model.getOutputAttributes().getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(NullAttributes.class.getName())); assertThat(model.getOutputAttributes().hasDynamicType(), is(false)); } /** * The operation returns the result of one of its routes, keeping the attributes of the result message. * * @param model the model to assert on */ private void assertAssociatedProcessorsChangeOutput(final OperationModel model) { assertThat(model.getOutput().getType(), instanceOf(DefaultAnyType.class)); assertThat(model.getOutput().hasDynamicType(), is(false)); assertThat(model.getOutputAttributes().getType(), instanceOf(DefaultObjectType.class)); assertThat(model.getOutputAttributes().getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(Attributes.class.getName())); assertThat(model.getOutputAttributes().hasDynamicType(), is(false)); } private void assertPayload(final ParameterModel payloadParameterModel) { assertThat(payloadParameterModel.getName(), is("payload")); assertThat(payloadParameterModel.getExpressionSupport(), is(SUPPORTED)); assertThat(payloadParameterModel.getType(), instanceOf(DefaultObjectType.class)); assertThat(payloadParameterModel.getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(Object.class.getName())); assertThat(payloadParameterModel.isRequired(), is(false)); } private void assertMultiPayload(final ParameterModel payloadParameterModel, String payloadVariableName, ExpressionSupport expressionSupport) { assertThat(payloadParameterModel.getName(), is(payloadVariableName)); assertThat(payloadParameterModel.getExpressionSupport(), is(expressionSupport)); assertThat(payloadParameterModel.getType(), instanceOf(DefaultArrayType.class)); assertThat(payloadParameterModel.getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(Iterable.class.getName())); assertThat(payloadParameterModel.isRequired(), is(expressionSupport == REQUIRED)); } private void assertTarget(final ParameterModel targetParameterModel) { assertThat(targetParameterModel.getName(), is("target")); assertThat(targetParameterModel.getExpressionSupport(), is(NOT_SUPPORTED)); assertThat(targetParameterModel.getType(), instanceOf(DefaultStringType.class)); assertThat(targetParameterModel.getType().getAnnotation(TypeIdAnnotation.class).get().getValue(), is(String.class.getName())); assertThat(targetParameterModel.isRequired(), is(false)); } }