/*
* Copyright 2008,2014 (C) Thomas Parker <thpr@users.sourceforge.net>
*
* 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 plugin.lsttokens;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import pcgen.cdom.base.CDOMObject;
import pcgen.cdom.base.CDOMReference;
import pcgen.cdom.base.ChooseDriver;
import pcgen.cdom.base.ChooseSelectionActor;
import pcgen.cdom.base.Constants;
import pcgen.cdom.base.Ungranted;
import pcgen.cdom.enumeration.ListKey;
import pcgen.cdom.reference.CDOMCompoundOrReference;
import pcgen.cdom.reference.ReferenceManufacturer;
import pcgen.cdom.reference.ReferenceUtilities;
import pcgen.core.PCTemplate;
import pcgen.core.PlayerCharacter;
import pcgen.persistence.PersistenceLayerException;
import pcgen.rules.context.Changes;
import pcgen.rules.context.LoadContext;
import pcgen.rules.persistence.TokenUtilities;
import pcgen.rules.persistence.token.AbstractToken;
import pcgen.rules.persistence.token.CDOMPrimaryToken;
import pcgen.rules.persistence.token.ParseResult;
/**
* @author djones4
*
*/
public class TemplateLst extends AbstractToken implements
CDOMPrimaryToken<CDOMObject>, ChooseSelectionActor<PCTemplate>
{
private static final String ADDCHOICE_COLON = "ADDCHOICE:";
private static final Class<PCTemplate> PCTEMPLATE_CLASS = PCTemplate.class;
@Override
public String getTokenName()
{
return "TEMPLATE";
}
@Override
public ParseResult parseToken(LoadContext context, CDOMObject cdo,
String value)
{
if (cdo instanceof Ungranted)
{
return new ParseResult.Fail("Cannot use " + getTokenName()
+ " on an Ungranted object type: "
+ cdo.getClass().getSimpleName(), context);
}
ListKey<CDOMReference<PCTemplate>> lk;
String remaining;
boolean consolidate = false;
boolean specialLegal = false;
if (value.startsWith(Constants.LST_CHOOSE_COLON))
{
lk = ListKey.TEMPLATE_CHOOSE;
remaining = value.substring(Constants.LST_CHOOSE_COLON.length());
consolidate = true;
}
else if (value.startsWith(ADDCHOICE_COLON))
{
lk = ListKey.TEMPLATE_ADDCHOICE;
remaining = value.substring(ADDCHOICE_COLON.length());
}
else
{
lk = ListKey.TEMPLATE;
remaining = value;
specialLegal = true;
}
if (isEmpty(remaining) || hasIllegalSeparator('|', remaining))
{
return ParseResult.INTERNAL_ERROR;
}
StringTokenizer tok = new StringTokenizer(remaining, Constants.PIPE);
List<CDOMReference<PCTemplate>> list = new ArrayList<>();
List<CDOMReference<PCTemplate>> removelist = new ArrayList<>();
while (tok.hasMoreTokens())
{
String templKey = tok.nextToken();
if (specialLegal && templKey.endsWith(".REMOVE"))
{
removelist.add(context.getReferenceContext().getCDOMReference(PCTEMPLATE_CLASS,
templKey.substring(0, templKey.length() - 7)));
}
else if (specialLegal && templKey.equals(Constants.LST_PERCENT_LIST))
{
context.getObjectContext().addToList(cdo,
ListKey.NEW_CHOOSE_ACTOR, this);
}
else
{
ReferenceManufacturer<PCTemplate> rm =
context.getReferenceContext().getManufacturer(
PCTEMPLATE_CLASS);
CDOMReference<PCTemplate> ref =
TokenUtilities.getTypeOrPrimitive(rm, templKey);
if (ref == null)
{
return ParseResult.INTERNAL_ERROR;
}
list.add(ref);
}
}
if (consolidate)
{
CDOMCompoundOrReference<PCTemplate> ref = new CDOMCompoundOrReference<>(
PCTEMPLATE_CLASS, Constants.LST_CHOOSE_COLON);
for (CDOMReference<PCTemplate> r : list)
{
ref.addReference(r);
}
ref.trimToSize();
list.clear();
list.add(ref);
}
for (CDOMReference<PCTemplate> ref : list)
{
context.getObjectContext().addToList(cdo, lk, ref);
}
if (!removelist.isEmpty())
{
for (CDOMReference<PCTemplate> ref : removelist)
{
context.getObjectContext().addToList(cdo,
ListKey.REMOVE_TEMPLATES, ref);
}
}
return ParseResult.SUCCESS;
}
@Override
public String[] unparse(LoadContext context, CDOMObject cdo)
{
Changes<CDOMReference<PCTemplate>> changes = context.getObjectContext()
.getListChanges(cdo, ListKey.TEMPLATE);
Changes<CDOMReference<PCTemplate>> removechanges = context
.getObjectContext().getListChanges(cdo,
ListKey.REMOVE_TEMPLATES);
Changes<ChooseSelectionActor<?>> listChanges = context
.getObjectContext().getListChanges(cdo,
ListKey.NEW_CHOOSE_ACTOR);
List<String> list = new ArrayList<>();
Collection<CDOMReference<PCTemplate>> added = changes.getAdded();
if (added != null && !added.isEmpty())
{
list.add(ReferenceUtilities.joinLstFormat(added, Constants.PIPE));
}
Collection<ChooseSelectionActor<?>> listAdded = listChanges.getAdded();
if (listAdded != null && !listAdded.isEmpty())
{
for (ChooseSelectionActor<?> csa : listAdded)
{
if (csa.equals(this))
{
list.add(Constants.LST_PERCENT_LIST);
}
}
}
Changes<CDOMReference<PCTemplate>> choosechanges = context
.getObjectContext()
.getListChanges(cdo, ListKey.TEMPLATE_CHOOSE);
Collection<CDOMReference<PCTemplate>> chadded = choosechanges
.getAdded();
if (chadded != null && !chadded.isEmpty())
{
for (CDOMReference<PCTemplate> ref : chadded)
{
list.add(Constants.LST_CHOOSE_COLON
+ ref.getLSTformat(false).replaceAll(",", "\\|"));
}
}
Changes<CDOMReference<PCTemplate>> addchanges = context
.getObjectContext().getListChanges(cdo,
ListKey.TEMPLATE_ADDCHOICE);
Collection<CDOMReference<PCTemplate>> addedItems = addchanges
.getAdded();
if (addedItems != null && !addedItems.isEmpty())
{
list.add(ADDCHOICE_COLON
+ ReferenceUtilities.joinLstFormat(addedItems,
Constants.PIPE));
}
Collection<CDOMReference<PCTemplate>> radd = removechanges.getAdded();
if (radd != null && !radd.isEmpty())
{
StringBuilder sb = new StringBuilder();
boolean needPipe = false;
for (CDOMReference<PCTemplate> ref : radd)
{
if (needPipe)
{
sb.append(Constants.PIPE);
}
needPipe = true;
sb.append(ref.getLSTformat(false)).append(".REMOVE");
}
list.add(sb.toString());
}
if (list.isEmpty())
{
// Possible if none triggered
return null;
}
return list.toArray(new String[list.size()]);
}
@Override
public Class<CDOMObject> getTokenClass()
{
return CDOMObject.class;
}
@Override
public void removeChoice(ChooseDriver owner, PCTemplate choice,
PlayerCharacter pc)
{
pc.removeTemplate(choice);
}
@Override
public void applyChoice(ChooseDriver owner, PCTemplate choice,
PlayerCharacter pc)
{
pc.addTemplate(choice);
}
@Override
public String getLstFormat() throws PersistenceLayerException
{
return Constants.LST_PERCENT_LIST;
}
@Override
public String getSource()
{
return getTokenName();
}
@Override
public Class<PCTemplate> getChoiceClass()
{
return PCTEMPLATE_CLASS;
}
}