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

org.mule.runtime.config.internal.model.ComponentModel 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.collect.ImmutableMap.copyOf;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableMap;
import static java.util.Optional.ofNullable;
import static org.mule.runtime.api.util.Preconditions.checkState;

import org.mule.runtime.api.component.ComponentIdentifier;
import org.mule.runtime.api.component.TypedComponentIdentifier;
import org.mule.runtime.config.internal.dsl.model.SpringComponentModel;
import org.mule.runtime.core.privileged.processor.Router;
import org.mule.runtime.dsl.api.component.config.ComponentConfiguration;
import org.mule.runtime.dsl.api.component.config.DefaultComponentLocation;
import org.mule.runtime.dsl.internal.component.config.InternalComponentConfiguration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;

/**
 * An {@code ComponentModel} represents the user configuration of a component (flow, config, message processor, etc) defined in an
 * artifact configuration file.
 * 

* Every {@code ComponentModel} represents the configuration of a core configuration or an extension configuration. Which * configuration element this object represents is identified by a {@link ComponentIdentifier} that can be retrieved using * {@code #getName}. *

* It may have simple configuration parameters which are retrieve by using {@code #getParameterGroups} or complex parameters which * are retrieved using {@code #getInnerComponents}. *

* There's a set of configuration attributes or custom attributes that may not be mapped directly to the object that runs on * runtime but may be hold by a {@code ComponentModel}. Those attributes are retrieved by using {@code #getCustomAttributes}. * * @since 4.0 */ public abstract class ComponentModel { public static String COMPONENT_MODEL_KEY = "ComponentModel"; private boolean root = false; private ComponentIdentifier identifier; private Map customAttributes = new HashMap<>(); private Map parameters = new HashMap<>(); private Set schemaValueParameter = new HashSet<>(); // TODO MULE-9638 This must go away from component model once it's immutable. private ComponentModel parent; private List innerComponents = new ArrayList<>(); private String textContent; private DefaultComponentLocation componentLocation; private TypedComponentIdentifier.ComponentType componentType; private Object objectInstance; private Class type; private Integer lineNumber; private String configFileName; private boolean enabled = true; /** * @return the line number in which the component was defined in the configuration file. It may be empty if the component was * created pragmatically. */ public Optional getLineNumber() { return ofNullable(lineNumber); } /** * @return the config file name in which the component was defined. It may be empty if the component was created pragmatically. */ public Optional getConfigFileName() { return ofNullable(configFileName); } /** * @return the configuration identifier. */ public ComponentIdentifier getIdentifier() { return identifier; } /** * @return a {@code java.util.Map} with the simple parameters of the configuration. */ public Map getParameters() { return unmodifiableMap(parameters); } /** * @return a {@code java.util.List} of all the child {@code ComponentModel}s */ public List getInnerComponents() { return innerComponents; } /** * @return a {@code java.util.Map} with all the custom attributes. */ public Map getCustomAttributes() { return copyOf(customAttributes); } /** * @return true if the {@code ComponentModel} is a top level configuration element, false otherwise. */ public boolean isRoot() { return root; } /** * Marked as true if it's a top level configuration. */ public void setRoot(boolean root) { this.root = root; } /** * @param parameterName name of the configuration parameter. * @param value value contained by the configuration parameter. */ public void setParameter(String parameterName, String value) { this.parameters.put(parameterName, value); } /** * @return the type of the object to be created when processing this {@code ComponentModel}. */ public Class getType() { return type; } /** * @param type the type of the object to be created when processing this {@code ComponentModel}. */ public void setType(Class type) { this.type = type; } /** * @return the {@link org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType} of the object to be created when processing this {@code ComponentModel}. */ public Optional getComponentType() { return ofNullable(componentType); } /** * @param componentType the {@link org.mule.runtime.api.component.TypedComponentIdentifier.ComponentType} of the object to be created when processing this {@code ComponentModel}. */ public void setComponentType(TypedComponentIdentifier.ComponentType componentType) { this.componentType = componentType; } /** * @return the value of the name attribute. */ public String getNameAttribute() { return parameters.get(ApplicationModel.NAME_ATTRIBUTE); } /** * @return true if this {@code ComponentModel} represents a {@code org.mule.runtime.core.api.processor.MessageProcessor} scope. */ public boolean isScope() { return Router.class.isAssignableFrom(type); } public void setParent(ComponentModel parent) { this.parent = parent; } /** * @return the parent component model in the configuration. */ public ComponentModel getParent() { return parent; } /** * @return content of the configuration element. */ public String getTextContent() { return textContent; } /** * @param componentLocation the location of the component in the configuration. */ public void setComponentLocation(DefaultComponentLocation componentLocation) { this.componentLocation = componentLocation; } /** * @return the location of the component in the configuration. */ public DefaultComponentLocation getComponentLocation() { return componentLocation; } /** * @return the object instance already created for this model */ public Object getObjectInstance() { return objectInstance; } /** * Setter used for components that should be created eagerly without going through spring. This is the case of models * contributing to IoC {@link org.mule.runtime.api.ioc.ObjectProvider} interface that require to be created before the * application components so they can be referenced. * * @param objectInstance the object instance created from this model. */ public void setObjectInstance(Object objectInstance) { this.objectInstance = objectInstance; } /** * @param parameterName configuration parameter name * @return true if the value provided for the configuration parameter was get from the DSL schema, false if it was explicitly * defined in the config */ public boolean isParameterValueProvidedBySchema(String parameterName) { return this.schemaValueParameter.contains(parameterName); } // TODO MULE-11355: Make the ComponentModel haven an ComponentConfiguration internally public ComponentConfiguration getConfiguration() { InternalComponentConfiguration.Builder builder = InternalComponentConfiguration.builder() .withIdentifier(this.getIdentifier()) .withValue(textContent); parameters.entrySet().forEach(e -> builder.withParameter(e.getKey(), e.getValue())); innerComponents.forEach(i -> builder.withNestedComponent(i.getConfiguration())); customAttributes.forEach(builder::withProperty); builder.withComponentLocation(this.componentLocation); builder.withProperty(COMPONENT_MODEL_KEY, this); return builder.build(); } /** * Sets the component as enabled, meaning that it should be created and the beanDefinition associated with created too. * * @param enabled if this component is enabled and has to be created. */ public void setEnabled(boolean enabled) { this.enabled = enabled; } /** * Executes the task on every inner component associated to this componentModel. * * @param task to be executed on inner components. */ public void executedOnEveryInnerComponent(final Consumer task) { for (ComponentModel componentModel : innerComponents) { task.accept(componentModel); componentModel.executedOnEveryInnerComponent(task); } } /** * @return {@code true} if this component is enabled and has to be created. */ public boolean isEnabled() { return this.enabled; } /** * Builder to create instances of {@code ComponentModel}. */ public static class Builder { private ComponentModel model = new SpringComponentModel(); private ComponentModel root; /** * Default constructor for this builder. */ public Builder() {} /** * Creates an instance of the Builder which will allow to merge other root component models to the given one. The root * component model provided here will be modified instead of cloned. * * @param root {@link ComponentModel} to be used as root. It will be modified. */ public Builder(ComponentModel root) { this.root = root; } /** * @param identifier identifier for the configuration element this object represents. * @return the builder. */ public Builder setIdentifier(ComponentIdentifier identifier) { checkIsNotBuildingFromRootComponentModel("identifier"); this.model.identifier = identifier; return this; } /** * @param parameterName name of the configuration parameter. * @param value value contained by the configuration parameter. * @param valueFromSchema * @return the builder. */ public Builder addParameter(String parameterName, String value, boolean valueFromSchema) { checkIsNotBuildingFromRootComponentModel("parameters"); this.model.parameters.put(parameterName, value); if (valueFromSchema) { this.model.schemaValueParameter.add(parameterName); } return this; } /** * Adds a new complex child object to this {@code ComponentModel}. * * @param componentModel child {@code ComponentModel} declared in the configuration. * @return the builder. */ public Builder addChildComponentModel(ComponentModel componentModel) { checkIsNotBuildingFromRootComponentModel("innerComponents"); this.model.innerComponents.add(componentModel); componentModel.setParent(model); return this; } /** * Sets the inner content of the configuration element. * * @param textContent inner text content from the configuration. * @return the builder. */ public Builder setTextContent(String textContent) { checkIsNotBuildingFromRootComponentModel("textComponent"); this.model.textContent = textContent; return this; } /** * When invoked the created {@code ComponentModel} will be marked us a top level configuration. * * @return the builder. */ public Builder markAsRootComponent() { checkIsNotBuildingFromRootComponentModel("root"); this.model.root = true; return this; } /** * Adds a custom attribute to the {@code ComponentModel}. This custom attribute is meant to hold metadata of the configuration * and not to be used to instantiate the runtime object that corresponds to this configuration. * * @param name custom attribute name. * @param value custom attribute value. * @return the builder. */ public Builder addCustomAttribute(String name, Object value) { checkIsNotBuildingFromRootComponentModel("customAttributes"); this.model.customAttributes.put(name, value); return this; } /** * @param configFileName the config file name in which this component was defined. * @return the builder. */ public Builder setConfigFileName(String configFileName) { checkIsNotBuildingFromRootComponentModel("configFileName"); this.model.configFileName = configFileName; return this; } /** * @param lineNumber the line number within the config file in which this component was defined. * @return the builder. */ public Builder setLineNumber(int lineNumber) { checkIsNotBuildingFromRootComponentModel("lineNumber"); this.model.lineNumber = lineNumber; return this; } /** * Given the following root component it will merge its customAttributes, parameters and schemaValueParameters to the root * component model. * * @param otherRootComponentModel another component model created as root to be merged. * @return the builder. */ public Builder merge(ComponentModel otherRootComponentModel) { this.root.customAttributes.putAll(otherRootComponentModel.customAttributes); this.root.parameters.putAll(otherRootComponentModel.parameters); this.root.schemaValueParameter.addAll(otherRootComponentModel.schemaValueParameter); this.root.innerComponents.addAll(otherRootComponentModel.innerComponents); return this; } /** * @return a {@code ComponentModel} created based on the supplied parameters. */ public ComponentModel build() { if (root != null) { return root; } checkState(model.identifier != null, "An identifier must be provided"); return model; } private void checkIsNotBuildingFromRootComponentModel(String parameter) { checkState(root == null, format("%s cannot be modified when builder has been constructed from a root component", parameter)); } } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ComponentModel that = (ComponentModel) o; if (root != that.root) { return false; } if (!identifier.equals(that.identifier)) { return false; } if (!parameters.equals(that.parameters)) { return false; } return innerComponents.equals(that.innerComponents); } @Override public int hashCode() { int result = (root ? 1 : 0); result = 31 * result + identifier.hashCode(); result = 31 * result + parameters.hashCode(); result = 31 * result + innerComponents.hashCode(); return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy