/*
* Copyright 2015 (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.text.MessageFormat;
import java.util.Set;
import java.util.TreeSet;
import pcgen.base.lang.CaseInsensitiveString;
import pcgen.base.text.MessageFormatUtilities;
import pcgen.cdom.base.CDOMObject;
import pcgen.cdom.base.Constants;
import pcgen.cdom.enumeration.MapKey;
import pcgen.rules.context.LoadContext;
import pcgen.rules.context.MapChanges;
import pcgen.rules.persistence.token.AbstractNonEmptyToken;
import pcgen.rules.persistence.token.CDOMPrimaryToken;
import pcgen.rules.persistence.token.DeferredToken;
import pcgen.rules.persistence.token.ParseResult;
import pcgen.util.Logging;
public class InfoLst extends AbstractNonEmptyToken<CDOMObject> implements
CDOMPrimaryToken<CDOMObject>, DeferredToken<CDOMObject>
{
@Override
public String getTokenName()
{
return "INFO";
}
@Override
protected ParseResult parseNonEmptyToken(LoadContext context,
CDOMObject cdo, String value)
{
if (value.charAt(0) == '|')
{
return new ParseResult.Fail(getTokenName()
+ " arguments may not start with PIPE : " + value);
}
if (value.charAt(value.length() - 1) == '|')
{
return new ParseResult.Fail(getTokenName()
+ " arguments may not end with PIPE : " + value);
}
int pipeLoc = value.indexOf(Constants.PIPE);
if (pipeLoc == -1)
{
return new ParseResult.Fail(getTokenName()
+ " expecting '|', format is: InfoName|Info value was: "
+ value, context);
}
String key = value.substring(0, pipeLoc);
//key length 0 caught by charAt(0) test above
String val = value.substring(pipeLoc + 1);
if (val.isEmpty())
{
return new ParseResult.Fail(getTokenName()
+ " expecting non-empty value, "
+ "format is: InfoName|Info value was: " + value, context);
}
if (val.startsWith(Constants.PIPE))
{
return new ParseResult.Fail(getTokenName()
+ " expecting non-empty value, "
+ "format is: InfoName|Info value was: " + value, context);
}
try
{
MessageFormat mf = new MessageFormat(val);
CaseInsensitiveString cis = new CaseInsensitiveString(key);
context.getObjectContext().put(cdo, MapKey.INFO, cis, mf);
}
catch (IllegalArgumentException e)
{
return new ParseResult.Fail(getTokenName()
+ " expected a valid MessageFormat, but received error: "
+ e.getMessage() + " when parsing: " + value, context);
}
return ParseResult.SUCCESS;
}
@Override
public String[] unparse(LoadContext context, CDOMObject cdo)
{
MapChanges<CaseInsensitiveString, MessageFormat> changes =
context.getObjectContext().getMapChanges(cdo, MapKey.INFO);
if (changes == null || changes.isEmpty())
{
return null;
}
Set<String> set = new TreeSet<>();
for (CaseInsensitiveString key : changes.getAdded().keySet())
{
MessageFormat value = changes.getAdded().get(key);
set.add(new StringBuilder().append(key).append(Constants.PIPE)
.append(value.toPattern()).toString());
}
return set.toArray(new String[set.size()]);
}
@Override
public Class<CDOMObject> getTokenClass()
{
return CDOMObject.class;
}
@Override
public boolean process(LoadContext context, CDOMObject obj)
{
boolean returnValue = true;
MapKey<CaseInsensitiveString, MessageFormat> infoKey = MapKey.INFO;
MapKey<CaseInsensitiveString, String[]> infoVarKey = MapKey.INFOVARS;
Set<CaseInsensitiveString> infoKeys = obj.getKeysFor(infoKey);
Set<CaseInsensitiveString> infoVarKeys = obj.getKeysFor(infoVarKey);
//Check if INFO needed INFOVARS
for (CaseInsensitiveString s : infoKeys)
{
MessageFormat mf = obj.get(infoKey, s);
int required = MessageFormatUtilities.getRequriedArgumentCount(mf);
if (required > 0)
{
String[] vars = obj.get(infoVarKey, s);
if (vars == null)
{
Logging.errorPrint(obj.getClass().getSimpleName() + " "
+ obj.getKeyName() + " was loaded with INFO: " + s
+ " that requires " + required
+ " arguments, but no arguments"
+ " in INFOVARS were provided", context);
returnValue = false;
}
else if (vars.length != required)
{
Logging.errorPrint(obj.getClass().getSimpleName() + " "
+ obj.getKeyName() + " was loaded with INFO: " + s
+ " that requires " + required + " arguments, but "
+ vars.length + " arguments in INFOVARS were provided",
context);
returnValue = false;
}
}
}
//Check if "Extra" INFOVARS were provided
for (CaseInsensitiveString s : infoVarKeys)
{
if (!infoKeys.contains(s))
{
Logging.errorPrint(
obj.getClass().getSimpleName() + " " + obj.getKeyName()
+ " was loaded with INFOVARS: " + s
+ " but no matching INFO was provided", context);
returnValue = false;
}
}
return returnValue;
}
@Override
public Class<CDOMObject> getDeferredTokenClass()
{
return CDOMObject.class;
}
}