/*
* bioSetLoader.java
* Copyright 2002 (C) Bryan McRoberts <merton_monk@yahoo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package pcgen.persistence.lst;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import pcgen.cdom.base.Constants;
import pcgen.cdom.base.TransitionChoice;
import pcgen.cdom.enumeration.ListKey;
import pcgen.core.AgeSet;
import pcgen.core.BioSet;
import pcgen.core.GameMode;
import pcgen.core.Kit;
import pcgen.core.PObject;
import pcgen.core.SystemCollections;
import pcgen.core.bonus.BonusObj;
import pcgen.persistence.PersistenceLayerException;
import pcgen.persistence.SystemLoader;
import pcgen.persistence.lst.prereq.PreParserFactory;
import pcgen.rules.context.LoadContext;
import pcgen.util.Logging;
/**
*
* @author Bryan McRoberts <merton_monk@yahoo.com>
*/
public final class BioSetLoader extends LstLineFileLoader
{
private static String regionName = Constants.NONE;
BioSet bioSet = new BioSet();
/**
* The age set (bracket) currently being processed. Used by the parseLine
* method to hold state between calls.
*/
int currentAgeSetIndex = 0;
/**
* clear the regionName
*/
public static void clear()
{
regionName = Constants.NONE;
}
/**
* @see pcgen.persistence.lst.LstLineFileLoader#loadLstFile(LoadContext, URI)
*/
@Override
public void loadLstFile(LoadContext context, URI fileName)
throws PersistenceLayerException
{
currentAgeSetIndex = 0;
final GameMode game = SystemCollections.getGameModeNamed(gameMode);
bioSet = game.getBioSet();
super.loadLstFile(context, fileName);
game.setBioSet(bioSet);
}
/**
* @see pcgen.persistence.lst.LstLineFileLoader#parseLine(LoadContext, String, URI)
*/
@Override
public void parseLine(LoadContext context, String lstLine, URI sourceURI)
{
if (lstLine.startsWith("AGESET:"))
{
String line = lstLine.substring(7);
int pipeLoc = line.indexOf('|');
if (pipeLoc == -1)
{
Logging.errorPrint("Found invalid AGESET " + "in Bio Settings "
+ sourceURI + ", was expecting a |: " + lstLine);
return;
}
String ageIndexString = line.substring(0, pipeLoc);
try
{
currentAgeSetIndex = Integer.parseInt(ageIndexString);
StringTokenizer colToken = new StringTokenizer(line
.substring(pipeLoc + 1), SystemLoader.TAB_DELIM);
AgeSet ageSet = new AgeSet(colToken.nextToken().intern(),
currentAgeSetIndex);
while (colToken.hasMoreTokens())
{
parseTokens(context, ageSet, colToken);
}
ageSet = bioSet.addToAgeMap(regionName, ageSet, sourceURI);
Integer oldIndex = bioSet.addToNameMap(ageSet);
if (oldIndex != null && oldIndex != currentAgeSetIndex)
{
Logging.errorPrint("Incompatible Index for AGESET "
+ "in Bio Settings " + sourceURI + ": " + oldIndex
+ " and " + currentAgeSetIndex + " for "
+ ageSet.getName());
}
}
catch (NumberFormatException e)
{
Logging.errorPrint("Illegal Index for AGESET "
+ "in Bio Settings " + sourceURI + ": "
+ ageIndexString + " was not an integer");
}
}
else
{
final StringTokenizer colToken = new StringTokenizer(lstLine,
SystemLoader.TAB_DELIM);
String colString;
String raceName = "";
List<String> preReqList = null;
while (colToken.hasMoreTokens())
{
colString = colToken.nextToken();
if (colString.startsWith("RACENAME:"))
{
raceName = colString.substring(9);
}
else if (colString.startsWith("REGION:"))
{
regionName = colString.substring(7).intern();
}
else if (PreParserFactory.isPreReqString(colString))
{
if (preReqList == null)
{
preReqList = new ArrayList<>();
}
preReqList.add(colString);
}
else
{
String aString = colString;
if (preReqList != null)
{
final StringBuilder sBuf = new StringBuilder(100+colString.length());
sBuf.append(colString);
for (String aPreReqList : preReqList)
{
sBuf.append('[').append(aPreReqList).append(
']');
}
aString = sBuf.toString();
}
bioSet.addToUserMap(regionName, raceName.intern(),
aString.intern(), currentAgeSetIndex);
}
}
}
}
private void parseTokens(LoadContext context, AgeSet ageSet, StringTokenizer tok)
{
final PObject dummy = new PObject();
try
{
while (tok.hasMoreTokens())
{
// in the code below, I use "new String()" to unlink the string from the containing file to save memory,
// but I don't intern() the string because it's not fully parsed yet so don't want to add permgen overhead
// to a string that's just going to get GC'd eventually
//
// This pessimization might be removable if we get all impls of CDOMToken.parseToken() to intern. But right
// now there are too many of them...
String currentTok = tok.nextToken();
if (currentTok.startsWith("BONUS:"))
{
if (context.processToken(dummy, "BONUS", new String(currentTok.substring(6))))
{
context.commit();
}
else
{
context.rollback();
Logging.errorPrint("Error in BONUS parse: " + currentTok);
Logging.replayParsedMessages();
}
}
else if (currentTok.startsWith("KIT:"))
{
if (context.processToken(dummy, "KIT", new String(currentTok.substring(4))))
{
context.commit();
}
else
{
context.rollback();
Logging.errorPrint("Error in KIT parse: " + currentTok);
Logging.replayParsedMessages();
}
}
else
{
Logging.errorPrint("Unexpected token in AGESET: " + currentTok);
}
}
List<BonusObj> bonuses = dummy.getListFor(ListKey.BONUS);
if (bonuses != null)
{
ageSet.addBonuses(bonuses);
}
List<TransitionChoice<Kit>> kits = dummy.getListFor(ListKey.KIT_CHOICE);
if (kits != null)
{
ageSet.addKits(kits);
}
}
catch (PersistenceLayerException e)
{
Logging.errorPrint("Error in token parse: "
+ e.getLocalizedMessage());
}
}
}