Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.mule.runtime.config.internal.dsl.model.ComponentLocationVisitor 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.dsl.model;
import static java.util.Collections.emptyList;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static org.mule.runtime.api.component.ComponentIdentifier.buildFromStringRepresentation;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.OPERATION;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.SCOPE;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.UNKNOWN;
import static org.mule.runtime.api.component.TypedComponentIdentifier.builder;
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.SUBFLOW_IDENTIFIER;
import static org.mule.runtime.config.internal.dsl.model.extension.xml.MacroExpansionModuleModel.ORIGINAL_IDENTIFIER;
import static org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper.isErrorHandler;
import static org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper.isMessageSource;
import static org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper.isProcessor;
import static org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper.isRouter;
import static org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper.isTemplateOnErrorHandler;
import static org.mule.runtime.config.internal.model.ApplicationModel.HTTP_PROXY_OPERATION_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.HTTP_PROXY_POLICY_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.HTTP_PROXY_SOURCE_POLICY_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.MODULE_OPERATION_CHAIN;
import static org.mule.runtime.config.internal.model.ApplicationModel.MUNIT_AFTER_SUITE_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.MUNIT_AFTER_TEST_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.MUNIT_BEFORE_SUITE_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.MUNIT_BEFORE_TEST_IDENTIFIER;
import static org.mule.runtime.config.internal.model.ApplicationModel.MUNIT_TEST_IDENTIFIER;
import org.mule.runtime.api.component.AbstractComponent;
import org.mule.runtime.api.component.ComponentIdentifier;
import org.mule.runtime.api.component.TypedComponentIdentifier;
import org.mule.runtime.api.component.location.ComponentLocation;
import org.mule.runtime.config.internal.dsl.spring.ComponentModelHelper;
import org.mule.runtime.config.internal.model.ApplicationModel;
import org.mule.runtime.config.internal.model.ComponentModel;
import org.mule.runtime.dsl.api.component.config.DefaultComponentLocation;
import org.mule.runtime.dsl.api.component.config.DefaultComponentLocation.DefaultLocationPart;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* Visitor that setups the {@link DefaultComponentLocation} for all mule components in the artifact configuration.
*
* @since 4.0
*/
// TODO MULE-13618 - Migrate ComponentLocationVisitor to use ExtensionModels
public class ComponentLocationVisitor implements Consumer {
public static final ComponentIdentifier BATCH_JOB_COMPONENT_IDENTIFIER = buildFromStringRepresentation("batch:job");
public static final ComponentIdentifier BATCH_PROCESSS_RECORDS_COMPONENT_IDENTIFIER =
buildFromStringRepresentation("batch:process-records");
private static final ComponentIdentifier BATCH_ON_COMPLETE_IDENTIFIER =
buildFromStringRepresentation("batch:on-complete");
private static final ComponentIdentifier BATCH_STEP_COMPONENT_IDENTIFIER = buildFromStringRepresentation("batch:step");
private static final ComponentIdentifier BATCH_AGGREGATOR_COMPONENT_IDENTIFIER =
buildFromStringRepresentation("batch:aggregator");
private static final String PROCESSORS_PART_NAME = "processors";
private static final ComponentIdentifier ROUTE_COMPONENT_IDENTIFIER = buildFromStringRepresentation("mule:route");
private static final ComponentIdentifier CHOICE_WHEN_COMPONENT_IDENTIFIER = buildFromStringRepresentation("mule:when");
private static final ComponentIdentifier CHOICE_OTHERWISE_COMPONENT_IDENTIFIER =
buildFromStringRepresentation("mule:otherwise");
private final ExtensionModelHelper extensionModelHelper;
public ComponentLocationVisitor(ExtensionModelHelper extensionModelHelper) {
this.extensionModelHelper = extensionModelHelper;
}
/**
* For every {@link ComponentModel} in the configuration, sets the {@link DefaultComponentLocation} associated within an
* annotation under the key {@link AbstractComponent#LOCATION_KEY}.
*
* @param componentModel the component model that will be assign it's {@link DefaultComponentLocation}.
*/
@Override
public void accept(ComponentModel componentModel) {
if (componentModel.getParent() == null) {
// do not process root element
return;
}
DefaultComponentLocation componentLocation;
Optional typedComponentIdentifier =
of(builder().identifier(componentModel.getIdentifier()).type(componentModel.getComponentType().orElse(UNKNOWN))
.build());
if (componentModel.isRoot()) {
String componentModelNameAttribute = componentModel.getNameAttribute();
ImmutableList parts =
ImmutableList.builder()
.add(new DefaultLocationPart(componentModelNameAttribute,
typedComponentIdentifier,
componentModel.getConfigFileName(),
componentModel.getLineNumber()))
.build();
componentLocation = new DefaultComponentLocation(ofNullable(componentModelNameAttribute), parts);
} else if (existsWithinRootContainer(componentModel)) {
ComponentModel parentComponentModel = componentModel.getParent();
DefaultComponentLocation parentComponentLocation = parentComponentModel.getComponentLocation();
if (isHttpProxyPart(componentModel)) {
componentLocation =
parentComponentLocation.appendLocationPart(componentModel.getIdentifier().getName(), typedComponentIdentifier,
componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else if (isRootProcessorScope(parentComponentModel)) {
componentLocation = processFlowDirectChild(componentModel, parentComponentLocation, typedComponentIdentifier);
} else if (isMunitFlowIdentifier(parentComponentModel)) {
componentLocation = parentComponentLocation.appendRoutePart()
.appendLocationPart(findNonProcessorPath(componentModel), typedComponentIdentifier,
componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else if (isErrorHandler(componentModel)) {
componentLocation = processErrorHandlerComponent(componentModel, parentComponentLocation, typedComponentIdentifier);
} else if (isTemplateOnErrorHandler(componentModel)) {
componentLocation = processOnErrorModel(componentModel, parentComponentLocation, typedComponentIdentifier);
} else if (parentComponentIsRouter(componentModel)) {
if (isRoute(componentModel)) {
componentLocation = parentComponentLocation.appendRoutePart()
.appendLocationPart(findNonProcessorPath(componentModel), of(TypedComponentIdentifier.builder().type(SCOPE)
.identifier(ROUTE_COMPONENT_IDENTIFIER).build()), componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else if (isProcessor(componentModel)) {
// this is the case of the routes directly inside the router as with scatter-gather
componentLocation = parentComponentLocation
.appendRoutePart()
.appendLocationPart(findProcessorPath(componentModel), empty(), empty(), empty())
.appendProcessorsPart()
.appendLocationPart("0", typedComponentIdentifier, componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else {
// this is the case of the when element inside the choice
componentLocation = parentComponentLocation.appendRoutePart()
.appendLocationPart(findNonProcessorPath(componentModel), of(TypedComponentIdentifier.builder().type(UNKNOWN)
.identifier(ROUTE_COMPONENT_IDENTIFIER).build()), empty(), empty());
}
} else if (isProcessor(componentModel)) {
if (isModuleOperation(componentModel.getParent())) {
final Optional operationTypedIdentifier =
ApplicationModel.MODULE_OPERATION_CHAIN.equals(typedComponentIdentifier.get().getIdentifier())
? getModuleOperationTypeComponentIdentifier(componentModel) : typedComponentIdentifier;
componentLocation = processModuleOperationChildren(componentModel, operationTypedIdentifier);
} else {
componentLocation = parentComponentLocation.appendProcessorsPart().appendLocationPart(findProcessorPath(componentModel),
typedComponentIdentifier,
componentModel
.getConfigFileName(),
componentModel.getLineNumber());
}
} else {
if (isBatchAggregator(componentModel)) {
componentLocation = parentComponentLocation
.appendLocationPart(BATCH_AGGREGATOR_COMPONENT_IDENTIFIER.getName(),
of(TypedComponentIdentifier.builder().type(UNKNOWN)
.identifier(BATCH_AGGREGATOR_COMPONENT_IDENTIFIER).build()),
componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else {
componentLocation =
parentComponentLocation.appendLocationPart(findNonProcessorPath(componentModel), typedComponentIdentifier,
componentModel.getConfigFileName(), componentModel.getLineNumber());
}
}
} else {
DefaultComponentLocation parentComponentLocation = componentModel.getParent().getComponentLocation();
componentLocation =
parentComponentLocation.appendLocationPart(findNonProcessorPath(componentModel), typedComponentIdentifier,
componentModel.getConfigFileName(), componentModel.getLineNumber());
}
componentModel.setComponentLocation(componentLocation);
}
private boolean isBatchAggregator(ComponentModel componentModel) {
return BATCH_AGGREGATOR_COMPONENT_IDENTIFIER.equals(componentModel.getIdentifier());
}
private boolean isRoute(ComponentModel componentModel) {
return componentModel.getIdentifier().equals(ROUTE_COMPONENT_IDENTIFIER)
|| componentModel.getIdentifier().equals(CHOICE_WHEN_COMPONENT_IDENTIFIER)
|| componentModel.getIdentifier().equals(CHOICE_OTHERWISE_COMPONENT_IDENTIFIER)
|| componentModel.getIdentifier().equals(BATCH_PROCESSS_RECORDS_COMPONENT_IDENTIFIER)
|| componentModel.getIdentifier().equals(BATCH_ON_COMPLETE_IDENTIFIER)
|| componentModel.getIdentifier().equals(BATCH_STEP_COMPONENT_IDENTIFIER);
}
private boolean isHttpProxyPart(ComponentModel componentModel) {
return componentModel.getIdentifier().equals(HTTP_PROXY_SOURCE_POLICY_IDENTIFIER)
|| componentModel.getIdentifier().equals(HTTP_PROXY_OPERATION_IDENTIFIER);
}
private boolean isMunitFlowIdentifier(ComponentModel componentModel) {
return componentModel.getIdentifier().equals(MUNIT_TEST_IDENTIFIER);
}
private boolean isRootProcessorScope(ComponentModel componentModel) {
ComponentIdentifier identifier = componentModel.getIdentifier();
return identifier.equals(FLOW_IDENTIFIER) || identifier.equals(MUNIT_BEFORE_SUITE_IDENTIFIER) ||
identifier.equals(MUNIT_BEFORE_TEST_IDENTIFIER) || identifier.equals(MUNIT_AFTER_SUITE_IDENTIFIER) ||
identifier.equals(MUNIT_AFTER_TEST_IDENTIFIER);
}
private boolean isModuleOperation(ComponentModel componentModel) {
return componentModel.getIdentifier().equals(MODULE_OPERATION_CHAIN);
}
private boolean parentComponentIsRouter(ComponentModel componentModel) {
return existsWithinRouter(componentModel) && isRouter(componentModel.getParent());
}
private boolean existsWithinRouter(ComponentModel componentModel) {
while (componentModel.getParent() != null) {
if (isRouter(componentModel)) {
return true;
}
componentModel = componentModel.getParent();
}
return false;
}
private String findNonProcessorPath(ComponentModel componentModel) {
// we just lookup the position of the component model within the children
int i = 0;
for (ComponentModel child : componentModel.getParent().getInnerComponents()) {
if (child == componentModel) {
break;
}
i++;
}
return String.valueOf(i);
}
private DefaultComponentLocation processOnErrorModel(ComponentModel componentModel,
DefaultComponentLocation parentComponentLocation,
Optional typedComponentIdentifier) {
ComponentModel parentComponentModel = componentModel.getParent();
int i = 0;
for (ComponentModel childComponent : parentComponentModel.getInnerComponents()) {
if (childComponent == componentModel) {
break;
}
i++;
}
return parentComponentLocation.appendLocationPart(String.valueOf(i), typedComponentIdentifier,
componentModel.getConfigFileName(), componentModel.getLineNumber());
}
private DefaultComponentLocation processFlowDirectChild(ComponentModel componentModel,
DefaultComponentLocation parentComponentLocation,
Optional typedComponentIdentifier) {
DefaultComponentLocation componentLocation;
if (isMessageSource(componentModel)) {
componentLocation =
parentComponentLocation.appendLocationPart("source", typedComponentIdentifier, componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else if (isProcessor(componentModel)) {
if (isModuleOperation(componentModel)) {
// just point to the correct typed component operation identifier
typedComponentIdentifier = getModuleOperationTypeComponentIdentifier(componentModel);
}
componentLocation = parentComponentLocation
.appendLocationPart(PROCESSORS_PART_NAME, empty(), empty(), empty())
.appendLocationPart(findProcessorPath(componentModel), typedComponentIdentifier, componentModel.getConfigFileName(),
componentModel.getLineNumber());
} else if (isErrorHandler(componentModel)) {
componentLocation = processErrorHandlerComponent(componentModel, parentComponentLocation, typedComponentIdentifier);
} else {
componentLocation =
parentComponentLocation.appendLocationPart(findNonProcessorPath(componentModel), typedComponentIdentifier,
componentModel.getConfigFileName(), componentModel.getLineNumber());
}
return componentLocation;
}
private Optional getModuleOperationTypeComponentIdentifier(ComponentModel componentModel) {
final ComponentIdentifier originalIdentifier =
(ComponentIdentifier) componentModel.getCustomAttributes().get(ORIGINAL_IDENTIFIER);
final String namespace = originalIdentifier.getNamespace();
final String operationName = originalIdentifier.getName();
final ComponentIdentifier operationIdentifier =
ComponentIdentifier.builder().namespace(namespace).name(operationName).build();
return of(builder().identifier(operationIdentifier).type(OPERATION).build());
}
/**
* It rewrites the history for those macro expanded operations that are not direct children from a flow, which means the
* returned {@link ComponentLocation} are mapped to the new operation rather the original flow.
*
* @param componentModel source to generate the new {@link ComponentLocation}, it also relies in its parent
* {@link ComponentModel#getParent()}
* @param operationTypedIdentifier identifier of the current operation
* @return a fictitious {@link ComponentLocation}
*/
private DefaultComponentLocation processModuleOperationChildren(ComponentModel componentModel,
Optional operationTypedIdentifier) {
final Optional parentOperationTypedIdentifier =
getModuleOperationTypeComponentIdentifier(componentModel.getParent());
final String operationName = parentOperationTypedIdentifier.get().getIdentifier().getName();
return new DefaultComponentLocation(of(operationName), emptyList())
.appendLocationPart(operationName, parentOperationTypedIdentifier, componentModel.getConfigFileName(),
componentModel.getLineNumber())
.appendLocationPart(PROCESSORS_PART_NAME, empty(), empty(), empty())
.appendLocationPart(findProcessorPath(componentModel), operationTypedIdentifier, componentModel.getConfigFileName(),
componentModel.getLineNumber());
}
private DefaultComponentLocation processErrorHandlerComponent(ComponentModel componentModel,
DefaultComponentLocation parentComponentLocation,
Optional typedComponentIdentifier) {
DefaultComponentLocation componentLocation;
componentLocation =
parentComponentLocation.appendLocationPart("errorHandler", typedComponentIdentifier,
componentModel.getConfigFileName(), componentModel.getLineNumber());
return componentLocation;
}
private String findProcessorPath(ComponentModel componentModel) {
ComponentModel parentComponentModel = componentModel.getParent();
List processorModels =
parentComponentModel.getInnerComponents().stream().filter(ComponentModelHelper::isProcessor).collect(Collectors.toList());
int i = 0;
for (ComponentModel processorModel : processorModels) {
if (processorModel == componentModel) {
break;
}
i++;
}
return String.valueOf(i);
}
private boolean existsWithinRootContainer(ComponentModel componentModel) {
return existsWithin(componentModel, FLOW_IDENTIFIER)
|| existsWithin(componentModel, MUNIT_TEST_IDENTIFIER)
|| existsWithin(componentModel, MUNIT_BEFORE_SUITE_IDENTIFIER)
|| existsWithin(componentModel, MUNIT_BEFORE_TEST_IDENTIFIER)
|| existsWithin(componentModel, MUNIT_AFTER_SUITE_IDENTIFIER)
|| existsWithin(componentModel, MUNIT_AFTER_TEST_IDENTIFIER)
|| existsWithin(componentModel, HTTP_PROXY_POLICY_IDENTIFIER)
|| existsWithinRootErrorHandler(componentModel)
|| existsWithinSubflow(componentModel);
}
private boolean existsWithinRootErrorHandler(ComponentModel componentModel) {
while (componentModel.getParent() != null) {
if (componentModel.getParent().getIdentifier().equals(ERROR_HANDLER_IDENTIFIER) && componentModel.getParent().isRoot()) {
return true;
}
componentModel = componentModel.getParent();
}
return false;
}
private boolean existsWithinSubflow(ComponentModel componentModel) {
return existsWithin(componentModel, SUBFLOW_IDENTIFIER);
}
private boolean existsWithin(ComponentModel componentModel, ComponentIdentifier componentIdentifier) {
while (componentModel.getParent() != null) {
if (componentModel.getParent().getIdentifier().equals(componentIdentifier)) {
return true;
}
componentModel = componentModel.getParent();
}
return false;
}
}