/*
* EquipSetMigration.java
* Copyright James Dempsey, 2013
*
* 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
*
* Created on 05/05/2013 12:54:09 PM
*
* $Id$
*/
package pcgen.io.migration;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import pcgen.cdom.enumeration.StringKey;
import pcgen.core.Equipment;
import pcgen.core.PlayerCharacter;
import pcgen.core.character.EquipSet;
import pcgen.core.utils.CoreUtility;
/**
* The Class {@code EquipSetMigration} updates a character's equipment
* sets to match newer requirements.
*
* <br>
*
* @author James Dempsey <jdempsey@users.sourceforge.net>
*/
public class EquipSetMigration
{
private static EquipSetOutputOrderComparator comparator =
new EquipSetOutputOrderComparator();
/**
* Update the character's equipment sets, if required.
*
* @param pc The character being updated.
* @param pcgVer The version of PCGen in which the character was created.
*/
public static void migrateEquipSets(PlayerCharacter pc, int pcgVer[])
{
if (CoreUtility.compareVersions(pcgVer, new int[]{6, 1, 3}) < 0)
{
renumberEquipmentSets(pc);
}
}
/**
* Renumber the equipment sets so that they are sortable in current output
* order. For each equipment set, change the format of the idpaths from
* 0.1.1.1 to 0.1.01.01 and renumber items in a container in accordance with
* their output order
* @param pc The character to have equipment sets renumbered.
*/
static void renumberEquipmentSets(PlayerCharacter pc)
{
Collection<EquipSet> allEquipSets = pc.getDisplay().getEquipSet();
List<EquipSet> sortedChildrenEs = getSortedChildren(allEquipSets, "0");
for (EquipSet equipSet : sortedChildrenEs)
{
List<EquipSet> children =
getSortedChildren(allEquipSets, equipSet.getIdPath());
renumberChildren(children, allEquipSets, equipSet.getIdPath());
}
}
/**
* Retrieve a list of the equipment sets underthe parent id path in id path order.
* @param allEquipSets The set of all equipment sets.
* @param parentIdPath The id path of the top of the tree we want to retrieve.
* @return The sorted list of child equipment sets.
*/
private static List<EquipSet> getSortedChildren(
Collection<EquipSet> allEquipSets, String parentIdPath)
{
List<EquipSet> children = new ArrayList<>();
for (EquipSet equipSet : allEquipSets)
{
if (equipSet.getParentIdPath().equals(parentIdPath))
{
children.add(equipSet);
}
}
children.sort(comparator);
return children;
}
/**
* Renumber the equipment sets in order with a potential new parent path
* also. This is a recursive function.
*
* @param targets The ordered list of equipment sets to be renumbered.
* @param allEquipSets The collection of all of the character's equipment sets.
* @param newParentPath The new path of the parent.
*/
private static void renumberChildren(List<EquipSet> targets,
Collection<EquipSet> allEquipSets, String newParentPath)
{
if (targets.isEmpty())
{
return;
}
int index = 1;
NumberFormat format = new DecimalFormat("00");
for (EquipSet equipSet : targets)
{
String oldIdPath = equipSet.getIdPath();
equipSet.setIdPath(newParentPath + "." + format.format(index++));
List<EquipSet> children =
getSortedChildren(allEquipSets, oldIdPath);
renumberChildren(children, allEquipSets, equipSet.getIdPath());
}
}
/** Comparator to order the equipment sets in output order. */
private static class EquipSetOutputOrderComparator implements
Comparator<EquipSet>
{
@Override
public int compare(EquipSet arg0, EquipSet arg1)
{
Equipment equip0 = arg0.getItem();
Equipment equip1 = arg1.getItem();
int equipOutputOrder0 =
equip0 == null ? 99999 : equip0.getOutputIndex();
int equipOutputOrder1 =
equip1 == null ? 99999 : equip1.getOutputIndex();
if (equipOutputOrder0 != equipOutputOrder1)
{
return ((Integer) equipOutputOrder0)
.compareTo(equipOutputOrder1);
}
String sortKey0 = getSortKey(equip0);
String sortKey1 = getSortKey(equip1);
if (!sortKey0.equals(sortKey1))
{
return sortKey0.compareTo(sortKey1);
}
return arg0.getIdPath().compareTo(arg1.getIdPath());
}
private String getSortKey(Equipment equip)
{
if (equip == null)
{
return "zzzzzzzz";
}
String key = equip.get(StringKey.SORT_KEY);
if (key == null)
{
key = equip.getDisplayName();
}
return key;
}
}
}