blob: c7842c038d67e3adfa88852622050ce63ee251d6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2008 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.common.internal.strategy;
import java.util.Iterator;
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
/**
* A composite strategy whos role is to iterate through a number of child
* stategies until one returns a valid value for an input.
*
* @author cbateman
*
* @param <INPUT>
* @param <OUTPUT>
* @param <RESULTOUTPUT>
* @param <IDTYPE>
* @param <STRATEGYTYPE>
*/
public abstract class StrategyComposite<INPUT, OUTPUT, RESULTOUTPUT, IDTYPE, STRATEGYTYPE extends IIdentifiableStrategy<INPUT, OUTPUT, IDTYPE>>
implements ISimpleStrategy<INPUT, RESULTOUTPUT>
{
private final AbstractCompositionStrategy<INPUT, OUTPUT, RESULTOUTPUT, STRATEGYTYPE> _compositionStrategy;
/**
* @param compositionStrategy
*/
protected StrategyComposite(
final AbstractCompositionStrategy<INPUT, OUTPUT, RESULTOUTPUT, STRATEGYTYPE> compositionStrategy)
{
_compositionStrategy = compositionStrategy;
}
/**
* Default constructor: composite returns the first value found.
*/
protected StrategyComposite()
{
// by default, the composition strategy selects the first value
this(
new DefaultCompositionStrategy<INPUT, OUTPUT, RESULTOUTPUT, STRATEGYTYPE>());
}
public final RESULTOUTPUT perform(final INPUT input)
{
final Iterator<STRATEGYTYPE> sIt = getIterator();
RESULTOUTPUT result = getNoResult();
boolean finishedComposing = false;
EXECUTE_LOOP: while (sIt.hasNext())
{
final STRATEGYTYPE strategy = sIt.next();
try
{
finishedComposing = _compositionStrategy
.compose(new CompositionArguments<INPUT, OUTPUT, STRATEGYTYPE>(
strategy, input));
// returns true if we are done composing
if (finishedComposing)
{
result = _compositionStrategy.getComposedResult();
break EXECUTE_LOOP;
}
} catch (final Exception e)
{
JSFCommonPlugin.log(e);
}
}
if (finishedComposing)
{
return result;
}
return getNoResult();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jst.jsf.common.internal.strategy.ISimpleStrategy#getNoResult
* ()
*/
public abstract RESULTOUTPUT getNoResult();
/**
* @return an iterator that will return the next strategy to be executed
*/
public abstract Iterator<STRATEGYTYPE> getIterator();
/**
* @author cbateman
* @param <INPUT>
* @param <OUTPUT>
* @param <RESULTOUTPUT>
* @param <STRATEGY>
*/
public abstract static class AbstractCompositionStrategy<INPUT, OUTPUT, RESULTOUTPUT, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
implements ISimpleStrategy<CompositionArguments<INPUT, OUTPUT, STRATEGY>, Boolean>
{
private final Boolean _noResultValue;
/**
*
*/
protected AbstractCompositionStrategy()
{
_noResultValue = null;
reset();
}
/**
* @param input
* @return true if composing is finished based on the input, false
* otherwise
* @throws Exception
*/
public abstract boolean compose(CompositionArguments<INPUT, OUTPUT, STRATEGY> input) throws Exception;
@SuppressWarnings("boxing")
public final Boolean perform(final CompositionArguments<INPUT, OUTPUT, STRATEGY> input) throws Exception
{
return compose(input);
}
/**
* @return the result of composing.
*/
public abstract RESULTOUTPUT getComposedResult();
public Boolean getNoResult()
{
return _noResultValue;
}
/**
* Clear any composed result and make strategy reusable as if it were
* newly constructed. This method is only called automatically at construction.
*
* Owners should call to control the contents of their result list.
*/
public abstract void reset();
}
/**
* The default composition strategy. This causes the first strategy that returns
* a non-NoResult value to have it's value returned.
*
* @param <INPUT>
* @param <OUTPUT>
* @param <RESULTOUTPUT>
* @param <STRATEGY>
*/
public final static class DefaultCompositionStrategy<INPUT, OUTPUT, RESULTOUTPUT, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
extends AbstractCompositionStrategy<INPUT, OUTPUT, RESULTOUTPUT, STRATEGY>
{
private RESULTOUTPUT _result;
/**
*
*/
public DefaultCompositionStrategy()
{
super();
}
@Override
public boolean compose(final CompositionArguments<INPUT, OUTPUT, STRATEGY> arg) throws Exception
{
final OUTPUT result = arg.getStrategy().perform(arg.getInput());
if (result != arg.getStrategy().getNoResult())
{
_result = (RESULTOUTPUT)result;
return true;
}
return false;
}
@Override
public RESULTOUTPUT getComposedResult()
{
return _result;
}
@Override
public void reset()
{
_result = null;
}
}
/**
* Bundle values needed by the composing strategies into a single arg object.
*
* @param <INPUT>
* @param <OUTPUT>
* @param <STRATEGY>
*/
public final static class CompositionArguments<INPUT, OUTPUT, STRATEGY extends ISimpleStrategy<INPUT, OUTPUT>>
{
private final STRATEGY _strategy;
private final INPUT _input;
/**
* @param strategy
* @param input
*/
public CompositionArguments(final STRATEGY strategy, final INPUT input)
{
_strategy = strategy;
_input = input;
}
/**
* @return the strategy
*/
public STRATEGY getStrategy()
{
return _strategy;
}
/**
* @return the input
*/
public INPUT getInput()
{
return _input;
}
}
}