// ==================================================================
// This file is part of Player API.
//
// Player API 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 3 of the
// License, or (at your option) any later version.
//
// Player API 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 and the GNU General Public License along with Player API.
// If not, see .
// ==================================================================
package api.player.server;
import java.util.*;
public final class ServerPlayerBaseSorter
{
public ServerPlayerBaseSorter(List list, Map allBaseSuperiors, Map allBaseInferiors, String methodName)
{
this.list = list;
this.allBaseSuperiors = allBaseSuperiors;
this.allBaseInferiors = allBaseInferiors;
this.methodName = methodName;
}
public void Sort()
{
if(list.size() <= 1)
return;
if(explicitInferiors != null)
explicitInferiors.clear();
if(explicitSuperiors != null)
explicitSuperiors.clear();
if(directInferiorsMap != null)
directInferiorsMap.clear();
if(allInferiors != null)
allInferiors.clear();
for(int i = 0; i < list.size(); i++)
{
String baseId = list.get(i);
String[] inferiorNames = allBaseInferiors.get(baseId);
boolean hasInferiors = inferiorNames != null && inferiorNames.length > 0;
String[] superiorNames = allBaseSuperiors.get(baseId);
boolean hasSuperiors = superiorNames != null && superiorNames.length > 0;
if((hasInferiors || hasSuperiors) && directInferiorsMap == null)
directInferiorsMap = new Hashtable>();
if(hasInferiors)
explicitInferiors = build(baseId, explicitInferiors, directInferiorsMap, null, inferiorNames);
if(hasSuperiors)
explicitSuperiors = build(baseId, explicitSuperiors, null, directInferiorsMap, superiorNames);
}
if(directInferiorsMap != null)
{
for(int i = 0; i < list.size() - 1; i++)
for(int n = i + 1; n < list.size(); n++)
{
String left = list.get(i);
String right = list.get(n);
Set leftInferiors = null, rightInferiors = null;
if(explicitInferiors != null)
{
leftInferiors = explicitInferiors.get(left);
rightInferiors = explicitInferiors.get(right);
}
Set leftSuperiors = null, rightSuperiors = null;
if(explicitSuperiors != null)
{
leftSuperiors = explicitSuperiors.get(left);
rightSuperiors = explicitSuperiors.get(right);
}
boolean leftWantsToBeInferiorToRight = leftSuperiors != null && leftSuperiors.contains(right);
boolean leftWantsToBeSuperiorToRight = leftInferiors != null && leftInferiors.contains(right);
boolean rightWantsToBeInferiorToLeft = rightSuperiors != null && rightSuperiors.contains(left);
boolean rightWantsToBeSuperiorToLeft = rightInferiors != null && rightInferiors.contains(left);
if(leftWantsToBeInferiorToRight && rightWantsToBeInferiorToLeft)
throw new UnsupportedOperationException("Can not sort ServerPlayerBase classes for method '" + methodName + "'. '" + left + "' wants to be inferior to '" + right + "' and '" + right + "' wants to be inferior to '" + left + "'");
if(leftWantsToBeSuperiorToRight && rightWantsToBeSuperiorToLeft)
throw new UnsupportedOperationException("Can not sort ServerPlayerBase classes for method '" + methodName + "'. '" + left + "' wants to be superior to '" + right + "' and '" + right + "' wants to be superior to '" + left + "'");
if(leftWantsToBeInferiorToRight && leftWantsToBeSuperiorToRight)
throw new UnsupportedOperationException("Can not sort ServerPlayerBase classes for method '" + methodName + "'. '" + left + "' wants to be superior and inferior to '" + right + "'");
if(rightWantsToBeInferiorToLeft && rightWantsToBeSuperiorToLeft)
throw new UnsupportedOperationException("Can not sort ServerPlayerBase classes for method '" + methodName + "'. '" + right + "' wants to be superior and inferior to '" + left + "'");
}
if(allInferiors == null)
allInferiors = new Hashtable>();
for(int i = 0; i < list.size(); i++)
build(list.get(i), null);
}
if (withoutSuperiors == null)
withoutSuperiors = new LinkedList();
int offset = 0;
int size = list.size();
while(size > 1)
{
withoutSuperiors.clear();
for(int i = offset; i < offset + size; i++)
withoutSuperiors.add(list.get(i));
if(allInferiors != null)
for(int i = offset; i < offset + size; i++)
{
Set inferiors = allInferiors.get(list.get(i));
if (inferiors != null)
withoutSuperiors.removeAll(inferiors);
}
boolean initial = true;
for(int i = offset; i < offset + size; i++)
{
String key = list.get(i);
if(withoutSuperiors.contains(key))
{
if(initial)
{
Set inferiors = null;
if(allInferiors != null)
inferiors = allInferiors.get(key);
if(inferiors == null || inferiors.isEmpty())
{
withoutSuperiors.remove(key);
size--;
offset++;
continue;
}
}
list.remove(i--);
size--;
}
initial = false;
}
list.addAll(offset + size, withoutSuperiors);
}
}
private Set build(String type, String startType)
{
Set inferiors = allInferiors.get(type);
if(inferiors == null)
{
inferiors = build(type, null, startType != null ? startType : type);
if(inferiors == null)
inferiors = Empty;
allInferiors.put(type, inferiors);
}
return inferiors;
}
private Set build(String type, Set inferiors, String startType)
{
Set directInferiors = directInferiorsMap.get(type);
if(directInferiors == null)
return inferiors;
if(inferiors == null)
inferiors = new HashSet();
Iterator iter = directInferiors.iterator();
while(iter.hasNext())
{
String inferiorType = iter.next();
if(inferiorType == startType)
throw new UnsupportedOperationException("Can not sort ServerPlayerBase classes for method '" + methodName + "'. Circular superiosity found including '" + startType + "'");
if(list.contains(inferiorType))
inferiors.add(inferiorType);
Set inferiorSet;
try
{
inferiorSet = build(inferiorType, startType);
}
catch(UnsupportedOperationException uoe)
{
throw new UnsupportedOperationException("Can not sort ServerPlayerBase classes for method '" + methodName + "'. Circular superiosity found including '" + inferiorType + "'", uoe);
}
if(inferiorSet != Empty)
inferiors.addAll(inferiorSet);
}
return inferiors;
}
private static Map> build(String baseId, Map> map, Map> directMap, Map> otherDirectMap, String[] names)
{
if(map == null)
map = new Hashtable>();
Set types = new HashSet();
for(int n = 0; n < names.length; n++)
{
if(names[n] != null)
types.add(names[n]);
}
if(directMap != null)
getOrCreateSet(directMap, baseId).addAll(types);
if(otherDirectMap != null)
{
Iterator iter = types.iterator();
while(iter.hasNext())
getOrCreateSet(otherDirectMap, iter.next()).add(baseId);
}
map.put(baseId, types);
return map;
}
private static Set getOrCreateSet(Map> map, String key)
{
Set value = map.get(key);
if(value != null)
return value;
value = new HashSet();
map.put(key, value);
return value;
}
private Map> explicitInferiors;
private Map> explicitSuperiors;
private Map> directInferiorsMap;
private Map> allInferiors;
private List withoutSuperiors;
private final List list;
private final Map allBaseSuperiors;
private final Map allBaseInferiors;
private final String methodName;
private static final Set Empty = new HashSet();
}