/*
Protocol Definition Language
Copyright (C) 2003-2006 Marcus Andersson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package net.sf.nmedit.jpdl2.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.nmedit.jpdl2.dom.PDLBlock;
import net.sf.nmedit.jpdl2.dom.PDLCaseStatement;
import net.sf.nmedit.jpdl2.dom.PDLFunction;
import net.sf.nmedit.jpdl2.dom.PDLItem;
import net.sf.nmedit.jpdl2.dom.PDLItemType;
import net.sf.nmedit.jpdl2.dom.PDLSwitchStatement;
import net.sf.nmedit.jpdl2.format.Expression;
public class PDLSwitchStatementImpl extends PDLItemImpl implements PDLSwitchStatement
{
private List<PDLCaseStatement> elements = new ArrayList<PDLCaseStatement>(2);
private List<PDLCaseStatement> publicCollection = Collections.unmodifiableList(elements);
private Map<Integer, PDLCaseStatement> caseList = new HashMap<Integer, PDLCaseStatement>();
private PDLCaseStatement defaultCase = null;
private int minimumCount = -1;
private int minimumSize = -1;
private PDLFunction function;
public PDLSwitchStatementImpl(Expression e)
{
this(new PDLFunctionImpl(e));
}
public PDLSwitchStatementImpl(PDLFunction function)
{
this.function = function;
if (function == null)
throw new NullPointerException();
}
public PDLFunction getFunction()
{
return function;
}
public void add(PDLCaseStatement c)
{
if (c == null)
throw new NullPointerException("element can not be null");
this.minimumCount = -1;
this.minimumSize = -1;
if (c.isDefaultCase())
{
for (PDLCaseStatement c2: elements)
if (c2.isDefaultCase())
throw new IllegalArgumentException("multiple default cases");
this.defaultCase = c;
}
else
{
// not default case
caseList.put(c.getValue(), c);
}
// ensure order, default is always at the end, other elements are ordered by value
for (int i=0;i<elements.size();i++)
{
if (elements.get(i).isDefaultCase())
{
elements.add(i, c);
return;
}
if (elements.get(i).getValue()<c.getValue())
{
elements.add(i+1, c);
return;
}
}
elements.add(c);
}
public Iterator<PDLCaseStatement> iterator()
{
return publicCollection.iterator();
}
public List<PDLCaseStatement> getItems()
{
return publicCollection;
}
public int getMinimumCount()
{
if (defaultCase == null)
return 0;
if (minimumCount<0)
{
int items = 0;
minimumCount = Integer.MAX_VALUE;
for (PDLCaseStatement casestmt: elements)
{
PDLItem item = casestmt.getBlock();
switch(item.getType())
{
case Optional: minimumCount = 0; break;
case Conditional: minimumCount = 0; break;
default:
{
items++;
minimumCount = Math.min(minimumCount, item.getMinimumCount());
break;
}
}
if (minimumCount == 0)
break;
}
if (items == 0)
minimumCount = 0;
}
return minimumCount;
}
public int getMinimumSize()
{
if (defaultCase == null)
return 0;
if (minimumSize<0)
{
int items = 0;
minimumSize = Integer.MAX_VALUE;
for (PDLCaseStatement casestmt: elements)
{
PDLItem item = casestmt.getBlock();
switch(item.getType())
{
case Optional: minimumSize = 0; break;
case Conditional: minimumSize = 0; break;
case Fail: break; // invalid path
default:
{
items++;
minimumSize = Math.min(minimumSize, item.getMinimumSize());
break;
}
}
if (minimumSize == 0)
break;
}
if (items == 0)
minimumSize = 0;
}
return minimumSize;
}
public PDLItemType getType()
{
return PDLItemType.SwitchStatement;
}
public PDLSwitchStatement asSwitchStatement()
{
return this;
}
public String toString()
{
return "switch ("+function+")";
}
public PDLBlock getItemForCase(int value)
{
PDLCaseStatement cs = caseList.get(value);
if (cs != null) return cs.getBlock();
if (defaultCase != null) return defaultCase.getBlock();
return null;
}
}