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

org.mule.runtime.config.internal.dsl.model.ExtensionModelHelper 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.singletonList;
import static java.util.Optional.empty;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.ERROR_HANDLER;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.FLOW;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.OPERATION;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.ROUTER;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.SCOPE;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.SOURCE;
import static org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType.UNKNOWN;
import static org.mule.runtime.api.util.NameUtils.COMPONENT_NAME_SEPARATOR;
import static org.mule.runtime.api.util.NameUtils.toCamelCase;
import static org.mule.runtime.config.internal.dsl.model.extension.xml.MacroExpansionModuleModel.ORIGINAL_IDENTIFIER;
import org.mule.runtime.api.component.ComponentIdentifier;
import org.mule.runtime.api.component.TypedComponentIdentifier;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.api.meta.model.ComponentModelVisitor;
import org.mule.runtime.api.meta.model.ExtensionModel;
import org.mule.runtime.api.meta.model.construct.ConstructModel;
import org.mule.runtime.api.meta.model.construct.HasConstructModels;
import org.mule.runtime.api.meta.model.nested.NestableElementModel;
import org.mule.runtime.api.meta.model.nested.NestableElementModelVisitor;
import org.mule.runtime.api.meta.model.nested.NestedChainModel;
import org.mule.runtime.api.meta.model.nested.NestedComponentModel;
import org.mule.runtime.api.meta.model.nested.NestedRouteModel;
import org.mule.runtime.api.meta.model.operation.HasOperationModels;
import org.mule.runtime.api.meta.model.operation.OperationModel;
import org.mule.runtime.api.meta.model.source.HasSourceModels;
import org.mule.runtime.api.meta.model.source.SourceModel;
import org.mule.runtime.api.util.Reference;
import org.mule.runtime.config.api.dsl.model.DslElementModel;
import org.mule.runtime.config.internal.model.ComponentModel;
import org.mule.runtime.extension.api.stereotype.MuleStereotypes;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;

/**
 * Helper class to work with a set of {@link ExtensionModel}s
 * 

* Contains a cache for searches within the extension models so we avoid processing each extension model twice. *

* It's recommended that the application only has one instance of this class to avoid processing the extension models several * times. * * since 4.0 */ public class ExtensionModelHelper { private final Set extensionsModels; private Cache> extensionComponentModelByComponentIdentifier = CacheBuilder.newBuilder().build(); /** * @param extensionModels the set of {@link ExtensionModel}s to work with. Usually this is the set of models configured within a * mule artifact. */ public ExtensionModelHelper(Set extensionModels) { this.extensionsModels = extensionModels; } /** * Find a {@link DslElementModel} for a given {@link ComponentModel} * * @param componentModel the component model from the configuration. * @return the {@link DslElementModel} associated with the configuration or an {@link Optional#empty()} if there isn't one. */ public TypedComponentIdentifier.ComponentType findComponentType(ComponentModel componentModel) { Optional extensionComponentModelOptional = findComponentModel(componentModel.getCustomAttributes().containsKey(ORIGINAL_IDENTIFIER) ? (ComponentIdentifier) componentModel.getCustomAttributes().get(ORIGINAL_IDENTIFIER) : componentModel.getIdentifier()); return extensionComponentModelOptional.map(extensionComponentModel -> { Reference componentTypeReference = new Reference<>(); extensionComponentModel.accept(new ComponentModelVisitor() { @Override public void visit(OperationModel model) { componentTypeReference.set(OPERATION); } @Override public void visit(SourceModel model) { componentTypeReference.set(SOURCE); } @Override public void visit(ConstructModel model) { if (model.getStereotype().equals(MuleStereotypes.ERROR_HANDLER)) { componentTypeReference.set(ERROR_HANDLER); return; } if (model.getStereotype().equals(MuleStereotypes.FLOW)) { componentTypeReference.set(FLOW); return; } NestedComponentVisitor nestedComponentVisitor = new NestedComponentVisitor(componentTypeReference); for (NestableElementModel nestableElementModel : model.getNestedComponents()) { nestableElementModel.accept(nestedComponentVisitor); if (componentTypeReference.get() != null) { return; } } } }); return componentTypeReference.get() == null ? UNKNOWN : componentTypeReference.get(); }).orElse(UNKNOWN); } /** * Finds a {@link org.mule.runtime.api.meta.model.ComponentModel} within the provided set of {@link ExtensionModel}s by a * {@link ComponentIdentifier}. * * @param componentIdentifier the identifier to use for the search. * @return the found {@link org.mule.runtime.api.meta.model.ComponentModel} or {@link Optional#empty()} if it couldn't be found. */ public Optional findComponentModel(ComponentIdentifier componentIdentifier) { try { return extensionComponentModelByComponentIdentifier.get(componentIdentifier, () -> { String componentName = toCamelCase(componentIdentifier.getName(), COMPONENT_NAME_SEPARATOR); for (ExtensionModel extensionModel : extensionsModels) { if (extensionModel.getXmlDslModel().getPrefix().equals(componentIdentifier.getNamespace())) { List operationModelsProviders = ImmutableList.builder() .add(extensionModel).addAll(extensionModel.getConfigurationModels()).build(); List sourceModelsProviders = ImmutableList.builder() .add(extensionModel).addAll(extensionModel.getConfigurationModels()).build(); List constructModelsProviders = singletonList(extensionModel); Optional componentModel = resolveModel(operationModelsProviders, sourceModelsProviders, constructModelsProviders, componentName); //TODO MULE-13894 remove this once unified extensionModel names to use camelCase (see smart connectors and crafted declared extesion models) if (!componentModel.isPresent()) { componentModel = resolveModel(operationModelsProviders, sourceModelsProviders, constructModelsProviders, componentIdentifier.getName()); } return componentModel; } } return empty(); }); } catch (ExecutionException e) { throw new MuleRuntimeException(e); } } private Optional resolveModel(List operationModelsProviders, List sourceModelsProviders, List constructModelsProviders, String componentName) { for (HasOperationModels operationModelsProvider : operationModelsProviders) { Optional operationModel = operationModelsProvider.getOperationModel(componentName); if (operationModel.isPresent()) { return operationModel; } } for (HasSourceModels sourceModelsProvider : sourceModelsProviders) { Optional sourceModel = sourceModelsProvider.getSourceModel(componentName); if (sourceModel.isPresent()) { return sourceModel; } } for (HasConstructModels constructModelsProvider : constructModelsProviders) { Optional constructModel = constructModelsProvider.getConstructModel(componentName); if (constructModel.isPresent()) { return constructModel; } } return empty(); } /** * Visitor of {@link ConstructModel} that determines it * {@link org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType} */ static class NestedComponentVisitor implements NestableElementModelVisitor { private Reference reference; public NestedComponentVisitor(Reference reference) { this.reference = reference; } @Override public void visit(NestedComponentModel component) {} @Override public void visit(NestedChainModel component) { reference.set(SCOPE); } @Override public void visit(NestedRouteModel component) { reference.set(ROUTER); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy