/*
* 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.spring.dsl.model;
import static java.util.Collections.emptySet;
import static java.util.Collections.singletonList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.rules.ExpectedException.none;
import static org.mockito.Mockito.mock;
import static org.mule.runtime.api.component.ComponentIdentifier.buildFromStringRepresentation;
import static org.mule.runtime.api.component.location.Location.builder;
import static org.mule.runtime.config.spring.XmlConfigurationDocumentLoader.schemaValidatingDocumentLoader;
import org.mule.runtime.api.app.declaration.ArtifactDeclaration;
import org.mule.runtime.api.component.location.Location;
import org.mule.runtime.config.spring.XmlConfigurationDocumentLoader;
import org.mule.runtime.config.spring.dsl.processor.ArtifactConfig;
import org.mule.runtime.config.spring.dsl.processor.ConfigFile;
import org.mule.runtime.config.spring.dsl.processor.ConfigLine;
import org.mule.runtime.config.spring.dsl.processor.xml.XmlApplicationParser;
import org.mule.runtime.core.api.registry.ServiceRegistry;
import org.mule.tck.junit4.AbstractMuleTestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class MinimalApplicationModelGeneratorTestCase extends AbstractMuleTestCase {
@Rule
public final ExpectedException expectedException = none();
private final ServiceRegistry mockServiceRegistry = mock(ServiceRegistry.class);
private final XmlApplicationParser xmlApplicationParser =
new XmlApplicationParser(mockServiceRegistry,
singletonList(MinimalApplicationModelGeneratorTestCase.class.getClassLoader()));
private final XmlConfigurationDocumentLoader documentLoader = schemaValidatingDocumentLoader();
@Test
public void noElements() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("no-elements-config.xml");
ApplicationModel minimalModel = generator.getMinimalModel(builder().globalName("flow").build());
assertThat(minimalModel.findNamedComponent("flow").isPresent(), is(true));
}
@Test
public void wrongElementIndexOnMinimalModelByPath() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("no-elements-config.xml");
Location nonExistentComponentLocation = builder().globalName("flow").addProcessorsPart().addIndexPart(3).build();
expectedException.expect(NoSuchComponentModelException.class);
expectedException.expectMessage("No object found at location " + nonExistentComponentLocation.toString());
generator.getMinimalModel(nonExistentComponentLocation);
}
@Test
public void singleElement() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("single-element-config.xml");
ApplicationModel minimalModel = generator.getMinimalModel(builder().globalName("errorHandler").build());
assertThat(minimalModel.findNamedComponent("errorHandler").isPresent(), is(true));
}
@Test
public void twoElements() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("two-elements-config.xml");
ApplicationModel minimalModel = generator.getMinimalModel(builder().globalName("flow").build());
assertThat(minimalModel.findNamedComponent("flow").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("errorHandler").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("errorHandler").get().isEnabled(), is(false));
}
@Test
public void dependencyBetweenElements() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("element-dependency-config.xml");
ApplicationModel minimalModel = generator.getMinimalModel(builder().globalName("flowOne").build());
assertThat(minimalModel.findNamedComponent("flowOne").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowTwo").isPresent(), is(true));
}
@Test
public void resolveDependencies() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("resolve-dependencies-config.xml");
ApplicationModel minimalModel =
generator.getMinimalModel(builder().globalName("flowTwo").addProcessorsPart().addIndexPart(0).build());
assertThat(minimalModel.findNamedComponent("flowTwo").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowTwo").get().isEnabled(), is(true));
assertThat(minimalModel.findNamedComponent("flowOne").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowOne").get().isEnabled(), is(false));
assertThat(minimalModel.findNamedComponent("flowWithSource").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().isEnabled(), is(false));
List<ComponentModel> componentModelList = generator.resolveComponentModelDependencies();
assertThat(componentModelList, hasSize(2));
assertThat(componentModelList.get(0).getNameAttribute(), equalTo("flowOne"));
assertThat(componentModelList.get(1).getNameAttribute(), equalTo("flowTwo"));
}
@Test
public void resolveDependenciesMultipleConfigFiles() throws Exception {
final String firstConfigFile = "resolve-dependencies-config-1.xml";
final String secondConfigFile = "resolve-dependencies-config-2.xml";
MinimalApplicationModelGenerator generator =
createGeneratorForConfig(firstConfigFile, secondConfigFile);
ApplicationModel minimalModel =
generator.getMinimalModel(builder().globalName("flowTwo").addProcessorsPart().addIndexPart(0).build());
assertThat(minimalModel.findNamedComponent("flowTwo").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowTwo").get().isEnabled(), is(true));
assertThat(minimalModel.findNamedComponent("flowOne").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowOne").get().isEnabled(), is(false));
assertThat(minimalModel.findNamedComponent("flowWithSource").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().isEnabled(), is(false));
List<ComponentModel> componentModelList = generator.resolveComponentModelDependencies();
assertThat(componentModelList, hasSize(2));
assertThat(componentModelList.get(0).getNameAttribute(), equalTo("flowOne"));
assertThat(componentModelList.get(1).getNameAttribute(), equalTo("flowTwo"));
assertThat(minimalModel.findNamedComponent("flowTwo").get().getConfigFileName().get(),
is(firstConfigFile));
assertThat(minimalModel.findNamedComponent("flowOne").get().getConfigFileName().get(),
is(secondConfigFile));
}
@Test
public void resolveCyclicDependencies() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("resolve-dependencies-cyclic-dependency-config.xml");
ApplicationModel minimalModel = generator.getMinimalModel(Location.builder().globalName("flowA").build());
assertThat(minimalModel.findNamedComponent("flowA").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowB").isPresent(), is(true));
List<ComponentModel> componentModelList = generator.resolveComponentModelDependencies();
assertThat(componentModelList, hasSize(2));
assertThat(componentModelList, containsInAnyOrder(hasProperty("nameAttribute", equalTo("flowB")),
hasProperty("nameAttribute", equalTo("flowA"))));
}
@Test
public void dependencyBetweenElementsReferencingMp() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("element-dependency-config.xml");
ApplicationModel minimalModel =
generator.getMinimalModel(builder().globalName("flowOne").addProcessorsPart().addIndexPart(0).build());
assertThat(minimalModel.findNamedComponent("flowOne").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowTwo").isPresent(), is(true));
}
@Test
public void noDependencyBetweenElementsReferencingMp() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("element-dependency-config.xml");
ApplicationModel minimalModel =
generator.getMinimalModel(builder().globalName("flowTwo").addProcessorsPart().addIndexPart(0).build());
assertThat(minimalModel.findNamedComponent("flowOne").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowTwo").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowTwo").get().isEnabled(), is(true));
}
@Test
public void flowWithSourcePathToMp() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("flow-source-config.xml");
ApplicationModel minimalModel =
generator.getMinimalModel(builder().globalName("flowWithSource").addProcessorsPart().addIndexPart(0).build());
assertThat(minimalModel.findNamedComponent("flowWithSource").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().size(), is(2));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().get(1).getIdentifier(),
is(buildFromStringRepresentation("mule:set-payload")));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().get(0).isEnabled(), is(false));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().get(1).isEnabled(), is(true));
}
@Test
public void flowWithSourcePathToSource() throws Exception {
MinimalApplicationModelGenerator generator = createGeneratorForConfig("flow-source-config.xml");
ApplicationModel minimalModel = generator.getMinimalModel(builder().globalName("flowWithSource").addSourcePart().build());
assertThat(minimalModel.findNamedComponent("flowWithSource").isPresent(), is(true));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().size(), is(2));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().get(0).getIdentifier(),
is(buildFromStringRepresentation("mule:scheduler")));
assertThat(minimalModel.findNamedComponent("flowWithSource").get().getInnerComponents().get(0).isEnabled(), is(true));
}
private MinimalApplicationModelGenerator createGeneratorForConfig(String... configFileName) throws Exception {
List<ConfigFile> configFiles = new ArrayList<>();
for (String configFile : configFileName) {
Optional<ConfigLine> configLine = xmlApplicationParser.parse(documentLoader
.loadDocument(configFile, getClass().getClassLoader().getResourceAsStream("model-generator/" + configFile))
.getDocumentElement());
configFiles.add(new ConfigFile(configFile, Arrays.asList(configLine.get())));
}
ComponentBuildingDefinitionRegistry componentBuildingDefinitionRegistry = new ComponentBuildingDefinitionRegistry();
CoreComponentBuildingDefinitionProvider coreComponentBuildingDefinitionProvider =
new CoreComponentBuildingDefinitionProvider();
coreComponentBuildingDefinitionProvider.init();
coreComponentBuildingDefinitionProvider.getComponentBuildingDefinitions()
.stream().forEach(componentBuildingDefinitionRegistry::register);
final ArtifactConfig.Builder builder = new ArtifactConfig.Builder();
configFiles.stream().forEach(configFile -> builder.addConfigFile(configFile));
final ArtifactConfig artifactConfig = builder.build();
return new MinimalApplicationModelGenerator(new ApplicationModel(artifactConfig, new ArtifactDeclaration(), emptySet(),
Optional.of(componentBuildingDefinitionRegistry)),
componentBuildingDefinitionRegistry);
}
}