All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mule.runtime.config.internal.model.ApplicationModel Maven / Gradle / Ivy

/*
 * 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.config.internal.model;

import static com.google.common.base.Joiner.on;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static java.util.Collections.singletonList;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.collections.CollectionUtils.disjunction;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.mule.runtime.api.component.ComponentIdentifier.builder;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.UNKNOWN;
import static org.mule.runtime.api.i18n.I18nMessageFactory.createStaticMessage;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.ERROR_HANDLER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.ERROR_HANDLER_IDENTIFIER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.FLOW_IDENTIFIER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.FLOW_REF_IDENTIFIER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.MULE_DOMAIN_IDENTIFIER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.MULE_EE_DOMAIN_IDENTIFIER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.MULE_IDENTIFIER;
import static org.mule.runtime.config.api.dsl.CoreDslConstants.MULE_ROOT_ELEMENT;
import static org.mule.runtime.config.internal.dsl.spring.BeanDefinitionFactory.SOURCE_TYPE;
import static org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper.resolveComponentType;
import static org.mule.runtime.core.api.el.ExpressionManager.DEFAULT_EXPRESSION_PREFIX;
import static org.mule.runtime.core.api.exception.Errors.Identifiers.ANY_IDENTIFIER;
import static org.mule.runtime.core.api.lifecycle.LifecycleUtils.initialiseIfNeeded;
import static org.mule.runtime.extension.api.util.NameUtils.hyphenize;
import static org.mule.runtime.extension.api.util.NameUtils.pluralize;
import static org.mule.runtime.internal.dsl.DslConstants.CORE_PREFIX;
import static org.mule.runtime.internal.util.NameValidationUtil.verifyStringDoesNotContainsReservedCharacters;
import org.mule.runtime.api.component.AbstractComponent;
import org.mule.runtime.api.component.Component;
import org.mule.runtime.api.component.ComponentIdentifier;
import org.mule.runtime.api.component.ConfigurationProperties;
import org.mule.runtime.api.component.TypedComponentIdentifier;
import org.mule.runtime.api.dsl.DslResolvingContext;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.api.i18n.I18nMessageFactory;
import org.mule.runtime.api.lifecycle.InitialisationException;
import org.mule.runtime.api.meta.model.ExtensionModel;
import org.mule.runtime.app.declaration.api.ArtifactDeclaration;
import org.mule.runtime.app.declaration.api.ElementDeclaration;
import org.mule.runtime.config.api.dsl.model.ComponentBuildingDefinitionRegistry;
import org.mule.runtime.config.api.dsl.model.ConfigurationParameters;
import org.mule.runtime.config.api.dsl.model.DslElementModelFactory;
import org.mule.runtime.config.api.dsl.model.ResourceProvider;
import org.mule.runtime.config.api.dsl.model.properties.ConfigurationPropertiesProvider;
import org.mule.runtime.config.api.dsl.model.properties.ConfigurationPropertiesProviderFactory;
import org.mule.runtime.config.api.dsl.model.properties.ConfigurationProperty;
import org.mule.runtime.config.api.dsl.processor.ArtifactConfig;
import org.mule.runtime.config.api.dsl.processor.ConfigFile;
import org.mule.runtime.config.api.dsl.processor.ConfigLine;
import org.mule.runtime.config.internal.dsl.model.ComponentLocationVisitor;
import org.mule.runtime.config.internal.dsl.model.ComponentModelReader;
import org.mule.runtime.config.internal.dsl.model.DefaultConfigurationParameters;
import org.mule.runtime.config.internal.dsl.model.ExtensionModelHelper;
import org.mule.runtime.config.internal.dsl.model.config.CompositeConfigurationPropertiesProvider;
import org.mule.runtime.config.internal.dsl.model.config.ConfigurationPropertiesResolver;
import org.mule.runtime.config.internal.dsl.model.config.DefaultConfigurationPropertiesResolver;
import org.mule.runtime.config.internal.dsl.model.config.DefaultConfigurationProperty;
import org.mule.runtime.config.internal.dsl.model.config.EnvironmentPropertiesConfigurationProvider;
import org.mule.runtime.config.internal.dsl.model.config.FileConfigurationPropertiesProvider;
import org.mule.runtime.config.internal.dsl.model.config.GlobalPropertyConfigurationPropertiesProvider;
import org.mule.runtime.config.internal.dsl.model.config.MapConfigurationPropertiesProvider;
import org.mule.runtime.config.internal.dsl.model.config.PropertiesResolverConfigurationProperties;
import org.mule.runtime.config.internal.dsl.model.config.RuntimeConfigurationException;
import org.mule.runtime.config.internal.dsl.model.extension.xml.MacroExpansionModulesModel;
import org.mule.runtime.config.internal.dsl.processor.ObjectTypeVisitor;
import org.mule.runtime.config.internal.dsl.processor.xml.XmlCustomAttributeHandler;
import org.mule.runtime.core.api.config.ConfigurationException;
import org.mule.runtime.core.api.extension.MuleExtensionModelProvider;
import org.mule.runtime.dsl.api.component.ComponentBuildingDefinition;
import org.mule.runtime.dsl.api.component.config.ComponentConfiguration;
import org.mule.runtime.dsl.api.component.config.DefaultComponentLocation;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import javax.xml.namespace.QName;

import org.apache.commons.lang3.ClassUtils;
import org.w3c.dom.Node;

/**
 * An {@code ApplicationModel} holds a representation of all the artifact configuration using an abstract model to represent any
 * configuration option.
 * 

* This model is represented by a set of {@link ComponentModel}. Each {@code ComponentModel} holds a piece of configuration and * may have children {@code ComponentModel}s as defined in the artifact configuration. *

* Once the set of {@code ComponentModel} gets created from the application * {@link org.mule.runtime.config.api.dsl.processor.ConfigFile}s the {@code ApplicationModel} executes a set of common validations * dictated by the configuration semantics. * * @since 4.0 */ public class ApplicationModel { // TODO MULE-9692 move this logic elsewhere. This are here just for the language rules and those should be processed elsewhere. public static final String POLICY_ROOT_ELEMENT = "policy"; public static final String ERROR_MAPPING = "error-mapping"; public static final String ON_ERROR = "on-error"; public static final String MAX_REDELIVERY_ATTEMPTS_ROLLBACK_ES_ATTRIBUTE = "maxRedeliveryAttempts"; public static final String WHEN_CHOICE_ES_ATTRIBUTE = "when"; public static final String TYPE_ES_ATTRIBUTE = "type"; public static final String EXCEPTION_STRATEGY_REFERENCE_ELEMENT = "exception-strategy"; public static final String PROPERTY_ELEMENT = "property"; public static final String NAME_ATTRIBUTE = "name"; public static final String REFERENCE_ATTRIBUTE = "ref"; public static final String VALUE_ATTRIBUTE = "value"; public static final String TRANSFORMER_REFERENCE_ELEMENT = "transformer"; public static final String ANNOTATION_ELEMENT = "annotations"; public static final String DATA_WEAVE = "weave"; public static final String CUSTOM_TRANSFORMER = "custom-transformer"; public static final String DESCRIPTION_ELEMENT = "description"; public static final String PROPERTIES_ELEMENT = "properties"; private static final String MODULE_OPERATION_CHAIN_ELEMENT = "module-operation-chain"; public static final String REDELIVERY_POLICY_ELEMENT = "redelivery-policy"; // TODO MULE-9638 Remove once all bean definitions parsers where migrated public static final String TEST_NAMESPACE = "test"; public static final String DOC_NAMESPACE = "doc"; public static final String SPRING_SECURITY_NAMESPACE = "ss"; public static final String MULE_SECURITY_NAMESPACE = "mule-ss"; public static final String MULE_XML_NAMESPACE = "mulexml"; public static final String PGP_NAMESPACE = "pgp"; public static final String XSL_NAMESPACE = "xsl"; public static final String TRANSPORT_NAMESPACE = "transports"; public static final String JMS_NAMESPACE = "jms"; public static final String VM_NAMESPACE = "vm"; public static final String HTTP_TRANSPORT_NAMESPACE = "http-transport"; public static final String BATCH_NAMESPACE = "batch"; public static final String PARSER_TEST_NAMESPACE = "parsers-test"; public static final String GLOBAL_PROPERTY = "global-property"; public static final String SECURITY_MANAGER = "security-manager"; public static final String OBJECT_ELEMENT = "object"; public static final ComponentIdentifier EXCEPTION_STRATEGY_REFERENCE_IDENTIFIER = builder().namespace(CORE_PREFIX).name(EXCEPTION_STRATEGY_REFERENCE_ELEMENT) .build(); public static final ComponentIdentifier ERROR_MAPPING_IDENTIFIER = builder().namespace(CORE_PREFIX).name(ERROR_MAPPING).build(); public static final ComponentIdentifier ON_ERROR_IDENTIFIER = builder().namespace(CORE_PREFIX).name(ON_ERROR).build(); public static final ComponentIdentifier MULE_PROPERTY_IDENTIFIER = builder().namespace(CORE_PREFIX).name(PROPERTY_ELEMENT).build(); public static final ComponentIdentifier MULE_PROPERTIES_IDENTIFIER = builder().namespace(CORE_PREFIX).name(PROPERTIES_ELEMENT).build(); public static final ComponentIdentifier ANNOTATIONS_ELEMENT_IDENTIFIER = builder().namespace(CORE_PREFIX).name(ANNOTATION_ELEMENT).build(); public static final ComponentIdentifier TRANSFORMER_IDENTIFIER = builder().namespace(CORE_PREFIX).name(TRANSFORMER_REFERENCE_ELEMENT).build(); public static final ComponentIdentifier CUSTOM_TRANSFORMER_IDENTIFIER = builder().namespace(CORE_PREFIX).name(CUSTOM_TRANSFORMER).build(); public static final ComponentIdentifier DOC_DESCRIPTION_IDENTIFIER = builder().namespace(DOC_NAMESPACE).name(DESCRIPTION_ELEMENT).build(); public static final ComponentIdentifier DESCRIPTION_IDENTIFIER = builder().namespace(CORE_PREFIX).name(DESCRIPTION_ELEMENT).build(); public static final ComponentIdentifier OBJECT_IDENTIFIER = builder().namespace(CORE_PREFIX).name(OBJECT_ELEMENT).build(); public static final ComponentIdentifier REDELIVERY_POLICY_IDENTIFIER = builder().namespace(CORE_PREFIX).name(REDELIVERY_POLICY_ELEMENT).build(); public static final ComponentIdentifier GLOBAL_PROPERTY_IDENTIFIER = builder().namespace(CORE_PREFIX).name(GLOBAL_PROPERTY).build(); public static final ComponentIdentifier SECURITY_MANAGER_IDENTIFIER = builder().namespace(CORE_PREFIX).name(SECURITY_MANAGER).build(); public static final ComponentIdentifier MODULE_OPERATION_CHAIN = builder().namespace(CORE_PREFIX).name(MODULE_OPERATION_CHAIN_ELEMENT).build(); // TODO MULE-13042 - remove this constants and their usages one this code gets migrated to use extension models. public static final String MUNIT_PREFIX = "munit"; public static final ComponentIdentifier MUNIT_TEST_IDENTIFIER = builder().namespace(MUNIT_PREFIX).name("test").build(); public static final ComponentIdentifier MUNIT_BEFORE_TEST_IDENTIFIER = builder().namespace(MUNIT_PREFIX).name("before-test").build(); public static final ComponentIdentifier MUNIT_BEFORE_SUITE_IDENTIFIER = builder().namespace(MUNIT_PREFIX).name("before-suite").build(); public static final ComponentIdentifier MUNIT_AFTER_TEST_IDENTIFIER = builder().namespace(MUNIT_PREFIX).name("after-test").build(); public static final ComponentIdentifier MUNIT_AFTER_SUITE_IDENTIFIER = builder().namespace(MUNIT_PREFIX).name("after-suite").build(); public static final String HTTP_POLICY = "http-policy"; public static final ComponentIdentifier HTTP_PROXY_SOURCE_POLICY_IDENTIFIER = builder().namespace(HTTP_POLICY).name("source").build(); public static final ComponentIdentifier HTTP_PROXY_OPERATION_IDENTIFIER = builder().namespace(HTTP_POLICY).name("operation").build(); public static final ComponentIdentifier HTTP_PROXY_POLICY_IDENTIFIER = builder().namespace(HTTP_POLICY).name("proxy").build(); public static final String CLASS_ATTRIBUTE = "class"; private static ImmutableSet ignoredNameValidationComponentList = ImmutableSet.builder() .add(builder().namespace(MULE_ROOT_ELEMENT).name("flow-ref").build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("alias").build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("password-encryption-strategy") .build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("custom-security-provider") .build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("custom-encryption-strategy") .build()) .add(builder().namespace(MULE_ROOT_ELEMENT) .name("secret-key-encryption-strategy") .build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("import").build()) .add(builder().namespace(MULE_ROOT_ELEMENT) .name("string-to-byte-array-transformer") .build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("append-string-transformer") .build()) .add(builder().namespace(MULE_ROOT_ELEMENT).name("security-manager").build()) .add(builder().namespace(TEST_NAMESPACE).name("queue").build()) .add(builder().namespace(TEST_NAMESPACE).name("invocation-counter").build()) .add(builder().namespace(SPRING_SECURITY_NAMESPACE).name("user").build()) .add(builder().namespace(MULE_SECURITY_NAMESPACE) .name("delegate-security-provider") .build()) .add(builder().namespace(MULE_SECURITY_NAMESPACE).name("security-manager") .build()) .add(builder().namespace(MULE_XML_NAMESPACE).name("xslt-transformer").build()) .add(builder().namespace(MULE_XML_NAMESPACE).name("alias").build()) .add(builder().namespace(PGP_NAMESPACE).name("security-provider").build()) .add(builder().namespace(PGP_NAMESPACE).name("keybased-encryption-strategy") .build()) .add(builder().namespace(XSL_NAMESPACE).name("param").build()) .add(builder().namespace(XSL_NAMESPACE).name("attribute").build()) .add(builder().namespace(XSL_NAMESPACE).name("element").build()) .add(builder().namespace(TRANSPORT_NAMESPACE).name("inbound-endpoint").build()) .add(builder().namespace(TRANSPORT_NAMESPACE).name("outbound-endpoint").build()) .add(builder().namespace(JMS_NAMESPACE).name("inbound-endpoint").build()) .add(builder().namespace(VM_NAMESPACE).name("inbound-endpoint").build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE).name("inbound-endpoint").build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE).name("set-cookie").build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE).name("header").build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE) .name("http-response-to-object-transformer") .build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE) .name("http-response-to-string-transformer") .build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE) .name("message-to-http-response-transformer") .build()) .add(builder().namespace(HTTP_TRANSPORT_NAMESPACE) .name("object-to-http-request-transformer") .build()) .add(builder().namespace(BATCH_NAMESPACE).name("step").build()) .add(builder().namespace(BATCH_NAMESPACE).name("execute").build()) .add(builder().namespace(PARSER_TEST_NAMESPACE).name("child").build()) .add(builder().namespace(PARSER_TEST_NAMESPACE).name("kid").build()) .add(builder().namespace(DATA_WEAVE).name("reader-property").build()) .build(); private final Optional componentBuildingDefinitionRegistry; private List muleComponentModels = new LinkedList<>(); private PropertiesResolverConfigurationProperties configurationProperties; private ResourceProvider externalResourceProvider; private Map namedComponentModels = new HashMap<>(); private Map namedTopLevelComponentModels = new HashMap<>(); /** * Creates an {code ApplicationModel} from a {@link ArtifactConfig}. *

* A set of validations are applied that may make creation fail. * * @param artifactConfig the mule artifact configuration content. * @param artifactDeclaration an {@link ArtifactDeclaration} * @throws Exception when the application configuration has semantic errors. */ public ApplicationModel(ArtifactConfig artifactConfig, ArtifactDeclaration artifactDeclaration, ResourceProvider externalResourceProvider) throws Exception { this(artifactConfig, artifactDeclaration, emptySet(), emptyMap(), empty(), of(new ComponentBuildingDefinitionRegistry()), true, externalResourceProvider); } /** * Creates an {code ApplicationModel} from a {@link ArtifactConfig}. *

* A set of validations are applied that may make creation fail. * * @param artifactConfig the mule artifact configuration content. * @param artifactDeclaration an {@link ArtifactDeclaration} * @param extensionModels Set of {@link ExtensionModel extensionModels} that will be used to type componentModels * @param parentConfigurationProperties the {@link ConfigurationProperties} of the parent artifact. For instance, application * will receive the domain resolver. * @param componentBuildingDefinitionRegistry an optional {@link ComponentBuildingDefinitionRegistry} used to correlate items in * this model to their definitions * @param runtimeMode true implies the mule application should behave as a runtime app (e.g.: smart connectors will be macro * expanded) false implies the mule is being created from a tooling perspective. * @param externalResourceProvider the provider for configuration properties files and ${file::name.txt} placeholders * @throws Exception when the application configuration has semantic errors. */ // TODO: MULE-9638 remove this optional public ApplicationModel(ArtifactConfig artifactConfig, ArtifactDeclaration artifactDeclaration, Set extensionModels, Map deploymentProperties, Optional parentConfigurationProperties, Optional componentBuildingDefinitionRegistry, boolean runtimeMode, ResourceProvider externalResourceProvider) throws Exception { this.componentBuildingDefinitionRegistry = componentBuildingDefinitionRegistry; this.externalResourceProvider = externalResourceProvider; createConfigurationAttributeResolver(artifactConfig, parentConfigurationProperties, deploymentProperties); convertConfigFileToComponentModel(artifactConfig); convertArtifactDeclarationToComponentModel(extensionModels, artifactDeclaration); resolveRegistrationNames(); createEffectiveModel(); indexComponentModels(); validateModel(componentBuildingDefinitionRegistry); ExtensionModelHelper extensionModelHelper = new ExtensionModelHelper(extensionModels); if (runtimeMode) { expandModules(extensionModels); // Have to index again the component models with macro expanded ones indexComponentModels(); } // TODO MULE-13894 do this only on runtimeMode=true once unified extensionModel names to use camelCase (see smart connectors // and crafted declared extesion models) resolveComponentTypes(); resolveTypedComponentIdentifier(extensionModelHelper); executeOnEveryMuleComponentTree(new ComponentLocationVisitor(extensionModelHelper)); } private void indexComponentModels() { executeOnEveryComponentTree(componentModel -> { if (componentModel.getNameAttribute() != null) { namedComponentModels.put(componentModel.getNameAttribute(), componentModel); } }); executeOnEveryRootElement(componentModel -> { if (componentModel.getNameAttribute() != null) { namedTopLevelComponentModels.put(componentModel.getNameAttribute(), componentModel); } }); } private void resolveTypedComponentIdentifier(ExtensionModelHelper extensionModelHelper) { executeOnEveryComponentTree(componentModel -> { Optional typedComponentIdentifier = of(TypedComponentIdentifier.builder().identifier(componentModel.getIdentifier()) .type(resolveComponentType(componentModel, extensionModelHelper)) .build()); componentModel.setComponentType(typedComponentIdentifier.map(typedIdentifier -> typedIdentifier.getType()) .orElse(TypedComponentIdentifier.ComponentType.UNKNOWN)); }); } private void createConfigurationAttributeResolver(ArtifactConfig artifactConfig, Optional parentConfigurationProperties, Map deploymentProperties) { EnvironmentPropertiesConfigurationProvider environmentPropertiesConfigurationProvider = new EnvironmentPropertiesConfigurationProvider(); ConfigurationPropertiesProvider globalPropertiesConfigurationAttributeProvider = createProviderFromGlobalProperties(artifactConfig); DefaultConfigurationPropertiesResolver localResolver = new DefaultConfigurationPropertiesResolver(of(new DefaultConfigurationPropertiesResolver( of(new DefaultConfigurationPropertiesResolver(empty(), environmentPropertiesConfigurationProvider)), globalPropertiesConfigurationAttributeProvider)), environmentPropertiesConfigurationProvider); List configConfigurationPropertiesProviders = getConfigurationPropertiesProvidersFromComponents(artifactConfig, localResolver); FileConfigurationPropertiesProvider externalPropertiesConfigurationProvider = new FileConfigurationPropertiesProvider(externalResourceProvider, "External files"); Optional parentConfigurationPropertiesResolver = of(localResolver); if (parentConfigurationProperties.isPresent()) { parentConfigurationPropertiesResolver = of(new DefaultConfigurationPropertiesResolver(empty(), new ConfigurationPropertiesProvider() { @Override public Optional getConfigurationProperty(String configurationAttributeKey) { return parentConfigurationProperties.get().resolveProperty(configurationAttributeKey) .map(value -> new DefaultConfigurationProperty(parentConfigurationProperties, configurationAttributeKey, value)); } @Override public String getDescription() { return "Domain properties"; } })); } if (!configConfigurationPropertiesProviders.isEmpty()) { CompositeConfigurationPropertiesProvider configurationAttributesProvider = new CompositeConfigurationPropertiesProvider(configConfigurationPropertiesProviders); parentConfigurationPropertiesResolver = of(new DefaultConfigurationPropertiesResolver(parentConfigurationPropertiesResolver, configurationAttributesProvider)); } DefaultConfigurationPropertiesResolver globalPropertiesConfigurationPropertiesResolver = new DefaultConfigurationPropertiesResolver(parentConfigurationPropertiesResolver, globalPropertiesConfigurationAttributeProvider); DefaultConfigurationPropertiesResolver systemPropertiesResolver = new DefaultConfigurationPropertiesResolver(of(globalPropertiesConfigurationPropertiesResolver), environmentPropertiesConfigurationProvider); DefaultConfigurationPropertiesResolver externalPropertiesResolver = new DefaultConfigurationPropertiesResolver(of(systemPropertiesResolver), externalPropertiesConfigurationProvider); if (deploymentProperties.isEmpty()) { this.configurationProperties = new PropertiesResolverConfigurationProperties(externalPropertiesResolver); } else { this.configurationProperties = new PropertiesResolverConfigurationProperties(new DefaultConfigurationPropertiesResolver(of(externalPropertiesResolver), new MapConfigurationPropertiesProvider(deploymentProperties, "Deployment properties"))); } } private List getConfigurationPropertiesProvidersFromComponents(ArtifactConfig artifactConfig, ConfigurationPropertiesResolver localResolver) { Map providerFactoriesMap = new HashMap<>(); ServiceLoader providerFactories = java.util.ServiceLoader.load(ConfigurationPropertiesProviderFactory.class); providerFactories.forEach(service -> { ComponentIdentifier componentIdentifier = service.getSupportedComponentIdentifier(); if (providerFactoriesMap.containsKey(componentIdentifier)) { throw new MuleRuntimeException(createStaticMessage("Multiple configuration providers for component: " + componentIdentifier)); } providerFactoriesMap.put(componentIdentifier, service); }); List configConfigurationPropertiesProviders = new ArrayList<>(); artifactConfig.getConfigFiles().stream() .forEach(configFile -> configFile.getConfigLines().stream() .forEach(configLine -> { for (ConfigLine componentConfigLine : configLine.getChildren()) { if (componentConfigLine.getNamespace() == null) { continue; } ComponentIdentifier componentIdentifier = ComponentIdentifier.builder() .namespace(componentConfigLine.getNamespace()).name(componentConfigLine.getIdentifier()).build(); if (!providerFactoriesMap.containsKey(componentIdentifier)) { continue; } DefaultConfigurationParameters.Builder configurationParametersBuilder = DefaultConfigurationParameters.builder(); ConfigurationParameters configurationParameters = resolveConfigurationParameters(configurationParametersBuilder, componentConfigLine, localResolver); ConfigurationPropertiesProvider provider = providerFactoriesMap.get(componentIdentifier) .createProvider(configurationParameters, externalResourceProvider); if (provider instanceof Component) { Component providerComponent = (Component) provider; TypedComponentIdentifier typedComponentIdentifier = TypedComponentIdentifier.builder() .type(UNKNOWN).identifier(componentIdentifier).build(); DefaultComponentLocation.DefaultLocationPart locationPart = new DefaultComponentLocation.DefaultLocationPart(componentIdentifier.getName(), of(typedComponentIdentifier), of(configFile.getFilename()), of(configLine.getLineNumber())); providerComponent.setAnnotations(ImmutableMap.builder() .put(AbstractComponent.LOCATION_KEY, new DefaultComponentLocation(of(componentIdentifier.getName()), singletonList(locationPart))) .build()); } configConfigurationPropertiesProviders.add(provider); try { initialiseIfNeeded(provider); } catch (InitialisationException e) { throw new MuleRuntimeException(e); } } })); return configConfigurationPropertiesProviders; } private ConfigurationParameters resolveConfigurationParameters(DefaultConfigurationParameters.Builder configurationParametersBuilder, ConfigLine componentConfigLine, ConfigurationPropertiesResolver localResolver) { componentConfigLine.getConfigAttributes().forEach((key, value) -> configurationParametersBuilder .withSimpleParameter(key, localResolver.resolveValue(value.getValue()))); for (ConfigLine childConfigLine : componentConfigLine.getChildren()) { DefaultConfigurationParameters.Builder childParametersBuilder = DefaultConfigurationParameters.builder(); configurationParametersBuilder.withComplexParameter(ComponentIdentifier.builder().name(childConfigLine.getIdentifier()) .namespace(childConfigLine.getNamespace()).build(), resolveConfigurationParameters(childParametersBuilder, childConfigLine, localResolver)); } return configurationParametersBuilder.build(); } /** * Resolves the types of each component model when possible. */ public void resolveComponentTypes() { // TODO MULE-13894 enable this once changes are completed and no componentBuildingDefinition is needed // checkState(componentBuildingDefinitionRegistry.isPresent(), // "ApplicationModel was created without a " + ComponentBuildingDefinitionProvider.class.getName()); componentBuildingDefinitionRegistry.ifPresent(buildingDefinitionRegistry -> { executeOnEveryComponentTree(componentModel -> { Optional> buildingDefinition = buildingDefinitionRegistry.getBuildingDefinition(componentModel.getIdentifier()); buildingDefinition.map(definition -> { ObjectTypeVisitor typeDefinitionVisitor = new ObjectTypeVisitor(componentModel); definition.getTypeDefinition().visit(typeDefinitionVisitor); componentModel.setType(typeDefinitionVisitor.getType()); return definition; }).orElseGet(() -> { String classParameter = componentModel.getParameters().get(CLASS_ATTRIBUTE); if (classParameter != null) { try { componentModel.setType(ClassUtils.getClass(classParameter)); } catch (ClassNotFoundException e) { throw new RuntimeConfigurationException(I18nMessageFactory.createStaticMessage(String .format("Could not resolve class '%s' for component '%s'", classParameter, componentModel.getComponentLocation()))); } } return null; }); }); }); } /** * Creates the effective application model to be used to generate the runtime objects of the mule configuration. */ private void createEffectiveModel() { processSourcesRedeliveryPolicy(); } /** * Process from any message source the redelivery-policy to make it part of the final pipeline. */ private void processSourcesRedeliveryPolicy() { executeOnEveryFlow(flowComponentModel -> { if (!flowComponentModel.getInnerComponents().isEmpty()) { ComponentModel possibleSourceComponent = flowComponentModel.getInnerComponents().get(0); possibleSourceComponent.getInnerComponents().stream() .filter(childComponent -> childComponent.getIdentifier().equals(REDELIVERY_POLICY_IDENTIFIER)) .findAny() .ifPresent(redeliveryPolicyComponentModel -> { possibleSourceComponent.getInnerComponents().remove(redeliveryPolicyComponentModel); flowComponentModel.getInnerComponents().add(1, redeliveryPolicyComponentModel); }); } }); } private void convertArtifactDeclarationToComponentModel(Set extensionModels, ArtifactDeclaration artifactDeclaration) { if (artifactDeclaration != null && !extensionModels.isEmpty()) { ExtensionModel muleModel = MuleExtensionModelProvider.getExtensionModel(); if (!extensionModels.contains(muleModel)) { extensionModels = new HashSet<>(extensionModels); extensionModels.add(muleModel); } DslElementModelFactory elementFactory = DslElementModelFactory.getDefault(DslResolvingContext.getDefault(extensionModels)); ComponentModel rootComponent = new ComponentModel.Builder() .setIdentifier(ComponentIdentifier.builder() .namespace(CORE_PREFIX) .name(CORE_PREFIX) .build()) .build(); AtomicBoolean atLeastOneComponentAdded = new AtomicBoolean(false); artifactDeclaration.getGlobalElements().stream() .map(e -> elementFactory.create((ElementDeclaration) e)) .filter(Optional::isPresent) .map(e -> e.get().getConfiguration()) .forEach(config -> config .ifPresent(c -> { atLeastOneComponentAdded.set(true); ComponentModel componentModel = convertComponentConfiguration(c, true); componentModel.setParent(rootComponent); rootComponent.getInnerComponents().add(componentModel); })); if (atLeastOneComponentAdded.get()) { this.muleComponentModels.add(rootComponent); } } } private ComponentModel convertComponentConfiguration(ComponentConfiguration componentConfiguration, boolean isRoot) { ComponentModel.Builder builder = new ComponentModel.Builder() .setIdentifier(componentConfiguration.getIdentifier()); if (isRoot) { builder.markAsRootComponent(); } for (Map.Entry parameter : componentConfiguration.getParameters().entrySet()) { builder.addParameter(parameter.getKey(), parameter.getValue(), false); } for (ComponentConfiguration childComponentConfiguration : componentConfiguration.getNestedComponents()) { builder.addChildComponentModel(convertComponentConfiguration(childComponentConfiguration, false)); } componentConfiguration.getValue().ifPresent(builder::setTextContent); ComponentModel componentModel = builder.build(); for (ComponentModel childComponent : componentModel.getInnerComponents()) { childComponent.setParent(componentModel); } return componentModel; } private ConfigurationPropertiesProvider createProviderFromGlobalProperties(ArtifactConfig artifactConfig) { final Map globalProperties = new HashMap<>(); artifactConfig.getConfigFiles().stream().forEach(configFile -> { configFile.getConfigLines().get(0).getChildren().stream().forEach(configLine -> { if (GLOBAL_PROPERTY.equals(configLine.getIdentifier())) { String key = configLine.getConfigAttributes().get("name").getValue(); String rawValue = configLine.getConfigAttributes().get("value").getValue(); globalProperties.put(key, new DefaultConfigurationProperty(format("global-property - file: %s - lineNumber %s", configFile.getFilename(), configLine.getLineNumber()), key, rawValue)); } }); }); return new GlobalPropertyConfigurationPropertiesProvider(globalProperties); } /** * @param element element which was the source of the {@code ComponentModel}. * @return the {@code ComponentModel} created from the element. */ // TODO MULE-9638: remove once the old parsing mechanism is not needed anymore public ComponentModel findComponentDefinitionModel(Node element) { return innerFindComponentDefinitionModel(element, muleComponentModels); } public Optional findComponentDefinitionModel(ComponentIdentifier componentIdentifier) { if (muleComponentModels.isEmpty()) { return empty(); } return muleComponentModels.get(0).getInnerComponents().stream().filter(ComponentModel::isRoot) .filter(componentModel -> componentModel.getIdentifier().equals(componentIdentifier)).findFirst(); } private void convertConfigFileToComponentModel(ArtifactConfig artifactConfig) { List configFiles = artifactConfig.getConfigFiles(); ComponentModelReader componentModelReader = new ComponentModelReader(configurationProperties.getConfigurationPropertiesResolver()); configFiles.stream().forEach(configFile -> { ComponentModel componentModel = componentModelReader.extractComponentDefinitionModel(configFile.getConfigLines().get(0), configFile.getFilename()); if (muleComponentModels.isEmpty()) { muleComponentModels.add(componentModel); } else { // Only one componentModel as Root should be set, therefore componentModel is merged final ComponentModel rootComponentModel = muleComponentModels.get(0); muleComponentModels.set(0, new ComponentModel.Builder(rootComponentModel).merge(componentModel).build()); } }); } private void validateModel(Optional componentBuildingDefinitionRegistry) throws ConfigurationException { if (muleComponentModels.isEmpty() || !isMuleConfigurationFile()) { return; } // TODO MULE-9692 all this validations will be moved to an entity that does the validation and allows to aggregate all // validations instead of failing fast. validateSingletonsAreNotRepeated(); validateNameIsNotRepeated(); validateNameHasValidCharacters(); validateFlowRefPointsToExistingFlow(); validateErrorMappings(); validateExceptionStrategyWhenAttributeIsOnlyPresentInsideChoice(); validateErrorHandlerStructure(); validateParameterAndChildForSameAttributeAreNotDefinedTogether(); if (componentBuildingDefinitionRegistry.isPresent()) { validateNamedTopLevelElementsHaveName(componentBuildingDefinitionRegistry.get()); } validateSingleElementsExistence(); } private void validateFlowRefPointsToExistingFlow() { executeOnEveryMuleComponentTree(componentModel -> { if (componentModel.getIdentifier().equals(FLOW_REF_IDENTIFIER)) { String nameAttribute = componentModel.getNameAttribute(); if (nameAttribute != null && !nameAttribute.startsWith(DEFAULT_EXPRESSION_PREFIX)) { Optional referencedFlow = findTopLevelNamedComponent(nameAttribute); referencedFlow .orElseThrow(() -> new MuleRuntimeException(createStaticMessage("flow-ref at %s:%s is pointing to %s which does not exist", componentModel.getConfigFileName() .orElse("unknown"), componentModel.getLineNumber().orElse(-1), nameAttribute))); } } }); } private void validateParameterAndChildForSameAttributeAreNotDefinedTogether() { executeOnEveryMuleComponentTree(componentModel -> { for (String parameterName : componentModel.getParameters().keySet()) { if (!componentModel.isParameterValueProvidedBySchema(parameterName)) { String mapChildName = hyphenize(pluralize(parameterName)); String listOrPojoChildName = hyphenize(parameterName); Optional childOptional = findRelatedChildForParameter(componentModel.getInnerComponents(), mapChildName, listOrPojoChildName); if (childOptional.isPresent()) { throw new MuleRuntimeException(createStaticMessage( format("Component %s has a child element %s which is used for the same purpose of the configuration parameter %s. " + "Only one must be used.", componentModel.getIdentifier(), childOptional.get().getIdentifier(), parameterName))); } } } }); } private Optional findRelatedChildForParameter(List chilrenComponents, String... possibleNames) { Set possibleNamesSet = new HashSet<>(asList(possibleNames)); for (ComponentModel childrenComponent : chilrenComponents) { if (possibleNamesSet.contains(childrenComponent.getIdentifier().getName())) { return of(childrenComponent); } } return empty(); } private void validateSingletonsAreNotRepeated() { Map existingObjectsWithName = new HashMap<>(); executeOnEveryRootElementWithBuildingDefinition(((componentModel, componentBuildingDefinition) -> { if (componentBuildingDefinition.getRegistrationName() != null) { String nameAttributeValue = componentModel.getNameAttribute(); if (existingObjectsWithName.containsKey(nameAttributeValue)) { ComponentModel otherComponentModel = existingObjectsWithName.get(nameAttributeValue); if (componentModel.getConfigFileName().isPresent() && componentModel.getLineNumber().isPresent() && otherComponentModel.getConfigFileName().isPresent() && otherComponentModel.getLineNumber().isPresent()) { throw new MuleRuntimeException(createStaticMessage( "The configuration element [%s] can only appear once, but was present in both [%s:%d] and [%s:%d]", componentModel.getIdentifier(), otherComponentModel.getConfigFileName().get(), otherComponentModel.getLineNumber().get(), componentModel.getConfigFileName().get(), componentModel.getLineNumber().get())); } else { throw new MuleRuntimeException(createStaticMessage( "The configuration element [%s] can only appear once, but was present multiple times", componentModel.getIdentifier())); } } existingObjectsWithName.put(nameAttributeValue, componentModel); componentModel.setParameter(ApplicationModel.NAME_ATTRIBUTE, componentBuildingDefinition.getRegistrationName()); } })); } private void validateNameIsNotRepeated() { Map existingObjectsWithName = new HashMap<>(); executeOnEveryRootElement(componentModel -> { String nameAttributeValue = componentModel.getNameAttribute(); if (nameAttributeValue != null && !ignoredNameValidationComponentList.contains(componentModel.getIdentifier())) { if (existingObjectsWithName.containsKey(nameAttributeValue)) { throw new MuleRuntimeException(createStaticMessage( "Two configuration elements have been defined with the same global name. Global name [%s] must be unique. Clashing components are %s and %s", nameAttributeValue, existingObjectsWithName.get(nameAttributeValue).getIdentifier(), componentModel.getIdentifier())); } existingObjectsWithName.put(nameAttributeValue, componentModel); } }); } private void validateNameHasValidCharacters() { executeOnEveryRootElement(componentModel -> { String nameAttributeValue = componentModel.getNameAttribute(); if (nameAttributeValue != null) { verifyStringDoesNotContainsReservedCharacters(nameAttributeValue); } }); } private boolean isMuleConfigurationFile() { final ComponentIdentifier rootIdentifier = muleComponentModels.get(0).getIdentifier(); return rootIdentifier.equals(MULE_IDENTIFIER) || rootIdentifier.equals(MULE_DOMAIN_IDENTIFIER) || rootIdentifier.equals(MULE_EE_DOMAIN_IDENTIFIER); } private void validateErrorMappings() { executeOnEveryComponentTree(componentModel -> { List errorMappings = componentModel.getInnerComponents().stream() .filter(c -> c.getIdentifier().equals(ERROR_MAPPING_IDENTIFIER)).collect(toList()); if (!errorMappings.isEmpty()) { List anyMappings = errorMappings.stream().filter(this::isErrorMappingWithSourceAny).collect(toList()); if (anyMappings.size() > 1) { throw new MuleRuntimeException(createStaticMessage("Only one mapping for 'ANY' or an empty source type is allowed.")); } else if (anyMappings.size() == 1 && !isErrorMappingWithSourceAny(errorMappings.get(errorMappings.size() - 1))) { throw new MuleRuntimeException(createStaticMessage("Only the last error mapping can have 'ANY' or an empty source type.")); } List sources = errorMappings.stream().map(model -> model.getParameters().get(SOURCE_TYPE)).collect(toList()); List distinctSources = sources.stream().distinct().collect(toList()); if (sources.size() != distinctSources.size()) { throw new MuleRuntimeException(createStaticMessage(format("Repeated source types are not allowed. Offending types are '%s'.", on("', '").join(disjunction(sources, distinctSources))))); } } }); } private boolean isErrorMappingWithSourceAny(ComponentModel model) { String sourceType = model.getParameters().get(SOURCE_TYPE); return sourceType == null || sourceType.equals(ANY_IDENTIFIER); } private void validateErrorHandlerStructure() { executeOnEveryMuleComponentTree(component -> { if (component.getIdentifier().equals(ERROR_HANDLER_IDENTIFIER)) { validateRefOrOnErrorsExclusiveness(component); validateOnErrorsHaveTypeOrWhenAttribute(component); validateNoMoreThanOneOnErrorPropagateWithRedelivery(component); } }); } private void validateRefOrOnErrorsExclusiveness(ComponentModel component) { if (component.getParameters().get(REFERENCE_ATTRIBUTE) != null && !component.getInnerComponents().isEmpty()) { throw new MuleRuntimeException(createStaticMessage("A reference error-handler cannot have on-errors.")); } } private void validateNoMoreThanOneOnErrorPropagateWithRedelivery(ComponentModel component) { if (component.getInnerComponents().stream().filter(exceptionStrategyComponent -> exceptionStrategyComponent.getParameters() .get(MAX_REDELIVERY_ATTEMPTS_ROLLBACK_ES_ATTRIBUTE) != null).count() > 1) { throw new MuleRuntimeException(createStaticMessage( "Only one on-error-propagate within a error-handler can handle message redelivery. Remove one of the maxRedeliveryAttempts attributes")); } } private void validateOnErrorsHaveTypeOrWhenAttribute(ComponentModel component) { List innerComponents = component.getInnerComponents(); for (int i = 0; i < innerComponents.size() - 1; i++) { ComponentModel componentModel = getOnErrorComponentModel(innerComponents.get(i)); Map parameters = componentModel.getParameters(); if (parameters.get(WHEN_CHOICE_ES_ATTRIBUTE) == null && parameters.get(TYPE_ES_ATTRIBUTE) == null) { throw new MuleRuntimeException(createStaticMessage( "Every handler (except for the last one) within an 'error-handler' must specify a 'when' or 'type' attribute.")); } } } private ComponentModel getOnErrorComponentModel(ComponentModel onErrorModel) { if (ON_ERROR_IDENTIFIER.equals(onErrorModel.getIdentifier())) { String sharedOnErrorName = onErrorModel.getParameters().get(REFERENCE_ATTRIBUTE); return findTopLevelNamedComponent(sharedOnErrorName).orElseThrow( () -> new MuleRuntimeException(createStaticMessage(format("Could not find on-error reference named '%s'", sharedOnErrorName)))); } else { return onErrorModel; } } private void validateExceptionStrategyWhenAttributeIsOnlyPresentInsideChoice() { executeOnEveryMuleComponentTree(component -> { if (component.getIdentifier().getName().endsWith(EXCEPTION_STRATEGY_REFERENCE_ELEMENT)) { Node componentNode = XmlCustomAttributeHandler.from(component).getNode(); if (component.getParameters().get(WHEN_CHOICE_ES_ATTRIBUTE) != null && !componentNode.getParentNode().getLocalName().equals(ERROR_HANDLER) && !componentNode.getParentNode().getLocalName().equals(MULE_ROOT_ELEMENT)) { throw new MuleRuntimeException( createStaticMessage("Only handlers within an error-handler can have when attribute specified")); } } }); } private void validateNamedTopLevelElementsHaveName(ComponentBuildingDefinitionRegistry componentBuildingDefinitionRegistry) throws ConfigurationException { try { List topLevelComponents = muleComponentModels.get(0).getInnerComponents(); topLevelComponents.stream().forEach(topLevelComponent -> { final ComponentIdentifier identifier = topLevelComponent.getIdentifier(); componentBuildingDefinitionRegistry.getBuildingDefinition(identifier).filter(ComponentBuildingDefinition::isNamed) .ifPresent(buildingDefinition -> { if (isBlank(topLevelComponent.getNameAttribute())) { throw new MuleRuntimeException(createStaticMessage(format("Global element %s:%s does not provide a name attribute.", identifier.getNamespace(), identifier.getName()))); } }); }); } catch (Exception e) { throw new ConfigurationException(e); } } public void executeOnEveryComponentTree(final Consumer task) { for (ComponentModel componentModel : muleComponentModels) { executeOnComponentTree(componentModel, task); } } public void executeOnEveryMuleComponentTree(final Consumer task) { for (ComponentModel componentModel : muleComponentModels) { executeOnComponentTree(componentModel, task); } } public void executeOnEveryRootElement(final Consumer task) { for (ComponentModel muleComponentModel : muleComponentModels) { for (ComponentModel componentModel : muleComponentModel.getInnerComponents()) { task.accept(componentModel); } } } public void executeOnEveryFlow(final Consumer task) { executeOnEveryRootElement(componentModel -> { if (FLOW_IDENTIFIER.equals(componentModel.getIdentifier())) { task.accept(componentModel); } }); } private void executeOnComponentTree(final ComponentModel component, final Consumer task) throws MuleRuntimeException { task.accept(component); component.getInnerComponents().forEach((innerComponent) -> { executeOnComponentTree(innerComponent, task); }); } private ComponentModel innerFindComponentDefinitionModel(Node element, List componentModels) { for (ComponentModel componentModel : componentModels) { if (XmlCustomAttributeHandler.from(componentModel).getNode().equals(element)) { return componentModel; } ComponentModel childComponentModel = innerFindComponentDefinitionModel(element, componentModel.getInnerComponents()); if (childComponentModel != null) { return childComponentModel; } } return null; } private void validateSingleElementsExistence() { validateSingleElementExistence(MUNIT_AFTER_SUITE_IDENTIFIER); validateSingleElementExistence(MUNIT_AFTER_SUITE_IDENTIFIER); validateSingleElementExistence(MUNIT_BEFORE_TEST_IDENTIFIER); validateSingleElementExistence(MUNIT_AFTER_TEST_IDENTIFIER); } private void validateSingleElementExistence(ComponentIdentifier componentIdentifier) { Map> existingComponentsPerFile = new HashMap<>(); executeOnEveryMuleComponentTree(componentModel -> { String configFileName = componentModel.getConfigFileName().get(); ComponentIdentifier identifier = componentModel.getIdentifier(); if (componentIdentifier.getNamespace().equals(identifier.getNamespace()) && componentIdentifier.getName().equals(identifier.getName())) { if (existingComponentsPerFile.containsKey(configFileName) && existingComponentsPerFile.get(configFileName).containsKey(identifier)) { throw new MuleRuntimeException(createStaticMessage( "Two configuration elements %s have been defined. Element [%s] must be unique. Clashing components are %s and %s", identifier.getNamespace() + ":" + identifier.getName(), identifier.getNamespace() + ":" + identifier.getName(), componentModel.getNameAttribute(), existingComponentsPerFile.get(configFileName).get(identifier) .getNameAttribute())); } Map existingComponentWithName = new HashMap<>(); existingComponentWithName.put(identifier, componentModel); existingComponentsPerFile.put(configFileName, existingComponentWithName); } }); } /** * TODO MULE-9688: When the model it's made immutable we will also provide the parent component for navigation and this will not * be needed anymore. * * @return the root component model */ public ComponentModel getRootComponentModel() { return muleComponentModels.get(0); } /** * Find a named component configuration. * * @param name the expected value for the name attribute configuration. * @return the component if present, if not, an empty {@link Optional} */ public Optional findTopLevelNamedComponent(String name) { return ofNullable(namedTopLevelComponentModels.getOrDefault(name, null)); } /** * Find a named component. * * @param name the expected value for the name attribute configuration. * @return the component if present, if not, an empty {@link Optional} */ public Optional findNamedElement(String name) { final Optional topLevelNamedComponent = findTopLevelNamedComponent(name); if (topLevelNamedComponent.isPresent()) { return topLevelNamedComponent; } return ofNullable(namedComponentModels.getOrDefault(name, null)); } /** * We force the current instance of {@link ApplicationModel} to be highly cohesive with {@link MacroExpansionModulesModel} as * it's responsibility of this object to properly initialize and expand every global element/operation into the concrete set of * message processors * * @param extensionModels Set of {@link ExtensionModel extensionModels} that will be used to check if the element has to be * expanded. */ private void expandModules(Set extensionModels) { new MacroExpansionModulesModel(this, extensionModels).expand(); } /** * @return the attributes resolver for this artifact. */ public ConfigurationProperties getConfigurationProperties() { return configurationProperties; } private void resolveRegistrationNames() { executeOnEveryRootElementWithBuildingDefinition((componentModel, componentBuildingDefinition) -> { if (componentBuildingDefinition.getRegistrationName() != null) { componentModel.setParameter(ApplicationModel.NAME_ATTRIBUTE, componentBuildingDefinition.getRegistrationName()); } }); } private void executeOnEveryRootElementWithBuildingDefinition(BiConsumer action) { if (componentBuildingDefinitionRegistry.isPresent()) { ComponentBuildingDefinitionRegistry definitionRegistry = componentBuildingDefinitionRegistry.get(); this.executeOnEveryRootElement(componentModel -> { Optional> buildingDefinition = definitionRegistry.getBuildingDefinition(componentModel.getIdentifier()); buildingDefinition.ifPresent(componentBuildingDefinition -> { action.accept(componentModel, componentBuildingDefinition); }); }); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy