package org.jboss.windup.config.phase;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.RuleProvider;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.MetadataBuilder;
import org.jboss.windup.config.metadata.RuleProviderMetadata;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.config.Rule;
/**
* Provides a shorthand for stating the order of execution of {@link Rule}s within Windup. When a {@link AbstractRuleProvider} specifies a
* {@link RulePhase}, the results of calling {@link RulePhase#getExecuteAfter()} and {@link RulePhase#getExecuteBefore()} on the rule will appended to
* the results of {@link RuleProviderMetadata#getExecuteAfter()} and {@link RulePhase#getExecuteBefore()}.
*
* In this way, most {@link AbstractRuleProvider}s will be able to simply specify a {@link RulePhase} in order to determine their approximate
* placement within the execution lifecycle.
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*/
public abstract class RulePhase extends AbstractRuleProvider
{
private final Class<? extends RulePhase> thisPhase;
private Class<? extends RulePhase> previousPhase;
private Class<? extends RulePhase> nextPhase;
public RulePhase(Class<? extends RulePhase> implementationType)
{
super(implementationType, implementationType.getSimpleName());
this.thisPhase = implementationType;
}
/**
* This will always return an empty {@link Configuration} as these are just barriers that do not provide additional
* {@link Rule}s.
*/
@Override
public final Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
return ConfigurationBuilder.begin();
}
@Override
public final RuleProviderMetadata getMetadata()
{
return MetadataBuilder.forProvider(thisPhase, thisPhase.getSimpleName())
/**
* We set {@link DependentPhase} because it has no executeBefore/executeAfter conditions of its own.
* The phase should provide it's own dependencies and not a recursive call to "getPhase()", so
* returning a value that has no dependencies of its own is necessary here.
*/
.setPhase(DependentPhase.class)
.addExecuteAfter(_getExecuteAfter())
.addExecuteBefore(_getExecuteBefore());
}
private Class<? extends RuleProvider> _getExecuteBefore()
{
return nextPhase == null ? getExecuteBefore() : nextPhase;
}
private Class<? extends RuleProvider> _getExecuteAfter()
{
return previousPhase == null ? getExecuteAfter() : previousPhase;
}
/**
* This allows the {@link RulePhase} implementation to specify the {@link RulePhase} implementation that it should
* be executed after.
*/
public abstract Class<? extends RulePhase> getExecuteAfter();
/**
* This allows the {@link RulePhase} implementation to specify the {@link RulePhase} implementation that it should
* be executed before.
*/
public abstract Class<? extends RulePhase> getExecuteBefore();
/**
* This allows the sorter to link {@link RulePhase}s to each other, without them having to explicitly specify both
* the executeAfter and executeBefore.
*/
public final void setExecuteAfter(Class<? extends RulePhase> previousPhase)
{
this.previousPhase = previousPhase;
}
/**
* This allows the sorter to link {@link RulePhase}s to each other, without them having to explicitly specify both
* the executeAfter and executeBefore.
*/
public final void setExecuteBefore(Class<? extends RulePhase> nextPhase)
{
this.nextPhase = nextPhase;
}
}