blob: 4e8cb428b32130debf8fc4b2de7a58d971e25b7f [file] [log] [blame]
package org.eclipse.jst.jsf.common.internal.strategy;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jst.jsf.common.internal.strategy.StrategyComposite.AbstractCompositionStrategy;
import org.eclipse.jst.jsf.common.internal.strategy.StrategyComposite.CompositionArguments;
/**
* A composition strategy that merges the result of all composed strategies. The
* merge policy is left to concrete implementations. Three concrete impls are
* provided: one that uses compose all (List) and one that uses compose unique
* (Set) and a third that uses Map.
*
* @author cbateman
*
* @param <INPUT>
* @param <MERGETYPE>
* @param <STRATEGY>
*/
/**
* @author cbateman
*
* @param <INPUT>
* @param <OUTPUT>
* @param <MERGETYPE>
* @param <STRATEGY>
*/
public abstract class MergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
extends AbstractCompositionStrategy<INPUT, OUTPUT, MERGETYPE, STRATEGY>
{
/**
* The result of the merge.
*/
protected final MERGETYPE _composedResult;
/**
* @param composedResult
* @param noResultValue
*/
public MergingCompositionStrategy(final MERGETYPE composedResult,
final MERGETYPE noResultValue)
{
super();
_composedResult = composedResult;
}
@Override
public boolean compose(final CompositionArguments<INPUT, OUTPUT, STRATEGY> args)
throws Exception
{
final OUTPUT result = args.getStrategy().perform(args.getInput());
if (result != args.getStrategy().getNoResult())
{
doCompose(result);
}
// never stop composing early
return false;
}
/**
* Sub-classes must implement to do the detail composition for their result
* type.
*
* @param result
*/
protected abstract void doCompose(OUTPUT result);
@Override
public MERGETYPE getComposedResult()
{
return _composedResult;
}
@Override
public abstract void reset();
/**
* An implementation that uses a List to implement the list policy. The
* result is to add all results from all composed strategies to a single
* list. Duplicates may occur.
*
* @param <INPUT>
* @param <OUTPUT>
* @param <MERGETYPE>
* @param <STRATEGY>
* `
*/
public static class ListMergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE extends List, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
extends
MergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE, STRATEGY>
{
/**
* @param composedResult
* @param noResultValue
*/
public ListMergingCompositionStrategy(final MERGETYPE composedResult,
final MERGETYPE noResultValue)
{
super(composedResult, noResultValue);
}
@Override
protected void doCompose(final OUTPUT result)
{
if (result instanceof Collection)
{
_composedResult.addAll((Collection) result);
} else
{
_composedResult.add(result);
}
}
@Override
public void reset()
{
_composedResult.clear();
}
}
/**
* An implementation that uses a List to implement the list policy. The
* result is to add all results from all composed strategies to a single
* list. Duplicates will not occur.
*
* @param <INPUT>
* @param <OUTPUT>
* @param <MERGETYPE>
* @param <STRATEGY>
*/
public static class SetMergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE extends Set, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
extends
MergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE, STRATEGY>
{
/**
* @param composedResult
* @param noResultValue
*/
public SetMergingCompositionStrategy(final MERGETYPE composedResult,
final MERGETYPE noResultValue)
{
super(composedResult, noResultValue);
}
@Override
protected void doCompose(final OUTPUT result)
{
if (result instanceof Collection)
{
_composedResult.addAll((Collection) result);
} else
{
_composedResult.add(result);
}
}
@Override
public void reset()
{
_composedResult.clear();
}
}
/**
* @author cbateman
*
* @param <INPUT>
* @param <OUTPUT>
* @param <MERGETYPE>
* @param <STRATEGY>
*/
public abstract static class MapMergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE extends Map, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
extends
MergingCompositionStrategy<INPUT, OUTPUT, MERGETYPE, STRATEGY>
{
/**
* @param composedResult
* @param noResultValue
*/
public MapMergingCompositionStrategy(final MERGETYPE composedResult,
final MERGETYPE noResultValue)
{
super(composedResult, noResultValue);
}
@Override
protected void doCompose(final OUTPUT result)
{
if (result instanceof Map)
{
_composedResult.putAll((Map) result);
} else
{
_composedResult.put(calculateKey(result), result);
}
}
/**
* @param result
* @return the key to be used for result in any composed map.
*/
protected abstract Object calculateKey(final OUTPUT result);
@Override
public void reset()
{
_composedResult.clear();
}
}
}