package cambridge.model;
import cambridge.ExpressionLanguage;
import cambridge.TemplateParsingException;
import cambridge.behaviors.ConditionalTagBehavior;
import java.util.ArrayList;
import java.util.Iterator;
import static cambridge.behaviors.ConditionalTagBehavior.ConditionType.FIRST;
/**
* @author Erdinc Yilmazel
* Date: Oct 13, 2009
* Time: 1:01:56 PM
*/
public class FragmentList extends ArrayList<Fragment>
{
final ExpressionLanguage expressionLanguage;
public FragmentList(ExpressionLanguage expressionLanguage)
{
this.expressionLanguage = expressionLanguage;
}
Fragment current;
public FragmentList append(String contents)
{
if (!(current instanceof StaticFragment))
{
if (current != null)
{
add(current);
}
current = new StaticFragment();
}
((StaticFragment) current).append(contents);
return this;
}
public void addFragment(Fragment f)
{
if (current != null)
{
add(current);
}
current = f;
}
private TagNode getNextTag(TagNode t)
{
TemplateNode next = t.getNextSibling();
TemplateNode nextNext = null;
if (next instanceof TextNode && ((TextNode) next).isWhiteSpace())
{
nextNext = next.getNextSibling();
}
return (next instanceof TagNode) ? (TagNode) next :
(nextNext instanceof TagNode) ? (TagNode) nextNext : null;
}
public void pack()
{
if (current != null)
{
add(current);
}
mergeConditionalBlocks();
for (Fragment f : this)
{
f.pack();
}
}
public ExpressionLanguage getExpressionLanguage()
{
return expressionLanguage;
}
private void mergeConditionalBlocks()
{
if (size() < 2)
{
return;
}
ArrayList<TagNode> conditionals = new ArrayList<TagNode>();
for (Fragment f : this)
{
if (f instanceof TagNode)
{
TagNode t = (TagNode) f;
ConditionalTagBehavior behavior = t.getConditionalBehavior();
if (behavior != null)
{
conditionals.add(t);
}
}
}
if (conditionals.size() == 0)
{
return;
}
ArrayList<ConditionalBlock> blocks = new ArrayList<ConditionalBlock>();
for (int i = 0; i < conditionals.size(); i++)
{
ConditionalBlock currentBlock = null;
TagNode t = conditionals.get(i);
ConditionalTagBehavior behavior = t.getConditionalBehavior();
main:
do
{
TagNode nextTag = getNextTag(t);
TagNode nextConditional = i + 1 < conditionals.size() ? conditionals.get(i + 1) : null;
if (currentBlock == null && behavior.getType() == FIRST
&& nextTag == nextConditional && nextTag != null
&& nextConditional.getConditionalBehavior().getType() != FIRST)
{
currentBlock = new ConditionalBlock(t);
}
if (nextTag == null || nextConditional == null)
{
break;
}
if (currentBlock == null && behavior.getType() != FIRST)
{
throw new TemplateParsingException(behavior.getValidationError(), nextTag.getBeginLine(), nextTag.getBeginColumn());
}
if (nextTag == nextConditional)
{
switch (nextTag.getConditionalBehavior().getType())
{
case FIRST:
break main;
case ALTERNATE:
currentBlock.addAlternateCondition(nextTag);
break;
case DEFAULT:
currentBlock.setDefaultCondition(nextTag);
i++;
t = nextTag;
break main;
}
}
else
{
break;
}
i++;
t = nextTag;
} while (true);
if (currentBlock != null)
{
if (currentBlock.isComplete())
{
blocks.add(currentBlock);
}
}
}
for (ConditionalBlock block : blocks)
{
TagNode first = block.getFirstTag();
TagNode last = block.getLastTag();
int i = 0;
Iterator<Fragment> iter = iterator();
boolean remove = false;
while (iter.hasNext())
{
Fragment cur = iter.next();
if (remove)
{
iter.remove();
}
if (cur == last)
{
break;
}
if (cur == first)
{
set(i, block);
remove = true;
}
i++;
}
}
}
}