/*
* FacadeFactory.java
* Copyright 2010 Connor Petty <cpmeister@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
*
* Created on Apr 7, 2010, 2:35:48 PM
*/
package pcgen.system;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pcgen.cdom.base.CDOMObject;
import pcgen.core.Campaign;
import pcgen.core.GameMode;
import pcgen.core.GameModeDisplay;
import pcgen.core.Globals;
import pcgen.core.SettingsHandler;
import pcgen.core.SystemCollections;
import pcgen.facade.core.CampaignFacade;
import pcgen.facade.core.CampaignInfoFactory;
import pcgen.facade.core.GameModeDisplayFacade;
import pcgen.facade.core.GameModeFacade;
import pcgen.facade.core.LoadableFacade.LoadingState;
import pcgen.facade.core.SourceSelectionFacade;
import pcgen.facade.util.DefaultListFacade;
import pcgen.facade.util.DefaultReferenceFacade;
import pcgen.facade.util.ListFacade;
import pcgen.facade.util.ListFacades;
import pcgen.facade.util.ReferenceFacade;
import pcgen.facade.util.WriteableReferenceFacade;
import pcgen.gui2.facade.Gui2CampaignInfoFactory;
import pcgen.persistence.PersistenceManager;
import pcgen.util.Logging;
import org.apache.commons.lang3.ArrayUtils;
/**
*
* @author Connor Petty <cpmeister@users.sourceforge.net>
*/
public class FacadeFactory
{
private static final PropertyContext sourcesContext = PCGenSettings.getInstance().createChildContext("customSources");
private static DefaultListFacade<SourceSelectionFacade> quickSources = null;
private static DefaultListFacade<CampaignFacade> campaigns = null;
private static DefaultListFacade<GameModeFacade> gamemodes = null;
private static DefaultListFacade<GameModeDisplayFacade> gamemodedisplays = null;
private static DefaultListFacade<SourceSelectionFacade> displayedSources = null;
private static DefaultListFacade<SourceSelectionFacade> customSources;
private static Map<String, CampaignFacade> campaignMap;
private static Map<GameModeFacade, DefaultListFacade<CampaignFacade>> campaignListMap = null;
private static final CampaignInfoFactory campInfoFactory = new Gui2CampaignInfoFactory();
static void initialize()
{
List<GameMode> modes = SystemCollections.getUnmodifiableGameModeList();
List<GameModeDisplay> modeDisplays = SystemCollections.getUnmodifiableGameModeDisplayList();
List<Campaign> camps = Globals.getCampaignList();
gamemodes = new DefaultListFacade<>(modes);
gamemodedisplays = new DefaultListFacade<>(modeDisplays);
campaigns = new DefaultListFacade<>(camps);
quickSources = new DefaultListFacade<>();
displayedSources = new DefaultListFacade<>();
customSources = new DefaultListFacade<>();
campaignMap = new HashMap<>();
campaignListMap = new HashMap<>();
initCampaigns();
initGameModes(modes);
initCustomSourceSelections();
initDisplayedSources();
}
public static void refresh()
{
List<GameMode> modes = SystemCollections.getUnmodifiableGameModeList();
List<GameModeDisplay> modeDisplays = SystemCollections.getUnmodifiableGameModeDisplayList();
List<Campaign> camps = Globals.getCampaignList();
gamemodes.setContents(modes);
gamemodedisplays.setContents(modeDisplays);
campaigns.setContents(camps);
quickSources.clearContents();
displayedSources.clearContents();
customSources.clearContents();
campaignMap.clear();
campaignListMap.clear();
initCampaigns();
initGameModes(modes);
initCustomSourceSelections();
initDisplayedSources();
}
private static void initCampaigns()
{
for (final CampaignFacade campaign : campaigns)
{
campaignMap.put(campaign.getName(), campaign);
ListFacade<GameModeFacade> gameModeList = campaign.getGameModes();
for (GameModeFacade gameModeFacade : gameModeList)
{
if (!campaignListMap.containsKey(gameModeFacade))
{
campaignListMap.put(gameModeFacade, new DefaultListFacade<>());
}
DefaultListFacade<CampaignFacade> campaignList = campaignListMap.get(gameModeFacade);
if (campaignList.containsElement(campaign))
{
String sourceUri = ((CDOMObject) campaign).getSourceURI().toString();
Logging.errorPrint("Campaign " + sourceUri
+ " lists GAMEMODE:" + gameModeFacade
+ " multiple times.");
}
else
{
campaignList.addElement(campaign);
}
}
if (campaign.showInMenu() && !gameModeList.isEmpty())
{
GameModeFacade game = gameModeList.getElementAt(0);
ListFacade<CampaignFacade> list =
new DefaultListFacade<>(Collections.singleton(campaign));
quickSources.addElement(new BasicSourceSelectionFacade(campaign.getName(), list, game));
}
}
}
private static void initGameModes(List<GameMode> modes)
{
for (GameMode mode : modes)
{
String title = mode.getDefaultSourceTitle();
if (SettingsHandler.getGame().equals(mode) && title == null && !mode.getDefaultDataSetList().isEmpty())
{
title = mode.getName();
}
if (title != null && !"".equals(title))
{
DefaultListFacade<CampaignFacade> qcamps = new DefaultListFacade<>();
List<String> sources = mode.getDefaultDataSetList();
for (String string : sources)
{
Campaign camp = Globals.getCampaignKeyed(string);
if (camp != null)
{
qcamps.addElement(camp);
}
else
{
Logging.log(Logging.WARNING, "Unable to find source "
+ string + " used in default source " + title
+ " for game mode " + mode + ". " + title
+ " might not work correctly.");
}
}
if (qcamps.isEmpty())
{
Logging.log(Logging.WARNING,
"Unable to load default source '" + title
+ "'. All of its sources are missing.");
continue;
}
quickSources.addElement(new BasicSourceSelectionFacade(mode.getDefaultSourceTitle(), qcamps, mode));
}
}
}
private static void initDisplayedSources()
{
String[] hiddenElements = PCGenSettings.getInstance().getStringArray("hiddenSources", ArrayUtils.EMPTY_STRING_ARRAY);
for (int i = 0; i < quickSources.getSize(); i++)
{
SourceSelectionFacade selection = quickSources.getElementAt(i);
if (!ArrayUtils.contains(hiddenElements, selection.toString()))
{
displayedSources.addElement(selection);
}
}
}
private static void initCustomSourceSelections()
{
String[] keys = sourcesContext.getStringArray("selectionNames");
if (keys == null)
{
return;
}
for (String name : keys)
{
PropertyContext context = sourcesContext.createChildContext(name);
String modeName = context.getProperty("gamemode");
GameMode mode = SystemCollections.getGameModeNamed(modeName);
if (mode == null)
{
Logging.errorPrint("Unable to load quick source '" + name +
"'. Game mode '" + modeName + "' is missing");
continue;
}
String[] selectionArray = context.getStringArray("campaigns");
List<CampaignFacade> sources = new ArrayList<>();
boolean error = false;
for (String campaign : selectionArray)
{
CampaignFacade c = campaignMap.get(campaign);
if (c != null)
{
sources.add(c);
}
else
{
error = true;
Logging.log(Logging.WARNING, "'" + campaign + "'" +
" campaign not found, custom quick source '" + name +
"' might not work correctly.");
}
}
if (sources.isEmpty())
{
Logging.errorPrint("Unable to load quick source '" + name +
"'. All of its sources are missing");
continue;
}
CustomSourceSelectionFacade selection = new CustomSourceSelectionFacade(name);
selection.setGameMode(mode);
selection.setCampaigns(sources);
if (error)
{
selection.setLoadingState(LoadingState.LOADED_WITH_ERRORS);
selection.setErrorMessage("Some campaigns are missing");
}
customSources.addElement(selection);
quickSources.addElement(selection);
}
}
public static SourceSelectionFacade createCustomSourceSelection(String name)
{
SourceSelectionFacade selection = new CustomSourceSelectionFacade(name);
customSources.addElement(selection);
quickSources.addElement(selection);
displayedSources.addElement(selection);
setCustomSourceSelectionArray();
return selection;
}
public static void deleteCustomSourceSelection(SourceSelectionFacade source)
{
if (!(source instanceof CustomSourceSelectionFacade))
{
throw new IllegalArgumentException();
}
customSources.removeElement(source);
quickSources.removeElement(source);
displayedSources.removeElement(source);
PropertyContext context = sourcesContext.createChildContext(source.toString());
context.removeProperty("gamemode");
context.removeProperty("campaigns");
setCustomSourceSelectionArray();
}
private static void setCustomSourceSelectionArray()
{
List<String> sources = new ArrayList<>();
for (SourceSelectionFacade csel : customSources)
{
sources.add(csel.toString());
}
sourcesContext.setStringArray("selectionNames", sources);
}
public static void setDisplayedSources(SourceSelectionFacade[] sources)
{
displayedSources.setContents(Arrays.asList(sources));
ArrayList<String> hiddenElements = new ArrayList<>();
for (SourceSelectionFacade selection : quickSources)
{
if (!ArrayUtils.contains(sources, selection))
{
hiddenElements.add(selection.toString());
}
}
PCGenSettings.getInstance().setStringArray("hiddenSources", hiddenElements);
}
public static SourceSelectionFacade createSourceSelection(
GameModeFacade gameMode, List<? extends CampaignFacade> campaignList)
{
return new BasicSourceSelectionFacade(null, new DefaultListFacade(
campaignList), gameMode);
}
public static SourceSelectionFacade createSourceSelection(
GameModeFacade gameMode, List<? extends CampaignFacade> campaignList,
String sourceTitle)
{
return new BasicSourceSelectionFacade(sourceTitle,
new DefaultListFacade(campaignList), gameMode);
}
/**
* returns a list of all SourceSelections that have not been hidden.
* @return a ListFacade containing SourceSelections
*/
public static ListFacade<SourceSelectionFacade> getDisplayedSourceSelections()
{
return displayedSources;
}
public static ListFacade<SourceSelectionFacade> getSourceSelections()
{
return quickSources;
}
public static ListFacade<SourceSelectionFacade> getCustomSourceSelections()
{
return customSources;
}
public static ListFacade<CampaignFacade> getCampaigns()
{
return campaigns;
}
public static ListFacade<GameModeFacade> getGameModes()
{
return gamemodes;
}
public static ListFacade<GameModeDisplayFacade> getGameModeDisplays()
{
return gamemodedisplays;
}
public static ListFacade<CampaignFacade> getSupportedCampaigns(GameModeFacade gameMode)
{
if (!campaignListMap.containsKey(gameMode))
{
return ListFacades.emptyList();
}
return campaignListMap.get(gameMode);
}
/**
* @return the Campaign Info Factory for the gui2 package.
*/
public static CampaignInfoFactory getCampaignInfoFactory()
{
return campInfoFactory;
}
public static boolean passesPrereqs(List<CampaignFacade> campaigns)
{
PersistenceManager pman = PersistenceManager.getInstance();
List<URI> oldList = pman.getChosenCampaignSourcefiles();
List<URI> uris = new ArrayList<>();
for (CampaignFacade campaignFacade : campaigns)
{
uris.add(((Campaign)campaignFacade).getSourceURI());
}
pman.setChosenCampaignSourcefiles(uris);
for (CampaignFacade campaignFacade : campaigns)
{
Campaign camp = ((Campaign)campaignFacade);
if(!camp.qualifies(null, camp))
{
pman.setChosenCampaignSourcefiles(oldList);
return false;
}
}
pman.setChosenCampaignSourcefiles(oldList);
return true;
}
private static class BasicSourceSelectionFacade implements SourceSelectionFacade
{
private final ListFacade<CampaignFacade> campaignModel;
private final DefaultReferenceFacade<GameModeFacade> gameModeRef;
private final String name;
private BasicSourceSelectionFacade(String name, ListFacade<CampaignFacade> campaignModel, GameModeFacade gameMode)
{
this.name = name;
this.campaignModel = campaignModel;
gameModeRef = new DefaultReferenceFacade<>(gameMode);
}
@Override
public void setCampaigns(List<CampaignFacade> campaign)
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setGameMode(GameModeFacade gameMode)
{
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean isModifiable()
{
return false;
}
@Override
public LoadingState getLoadingState()
{
return LoadingState.LOADED;
}
@Override
public String getLoadingErrorMessage()
{
return null;
}
@Override
public String toString()
{
if (name != null)
{
return name;
}
if (gameModeRef != null && gameModeRef.get() != null)
{
return LanguageBundle.getFormattedString("in_source_gamemode",
gameModeRef.get().getDisplayName());
}
return "";
}
@Override
public ListFacade<CampaignFacade> getCampaigns()
{
return campaignModel;
}
@Override
public ReferenceFacade<GameModeFacade> getGameMode()
{
return gameModeRef;
}
}
private static final class CustomSourceSelectionFacade implements SourceSelectionFacade
{
private final PropertyContext context;
private final String name;
private LoadingState loadingState = LoadingState.LOADED;
private String errorMessage = null;
private CustomSourceSelectionFacade(String name)
{
this.name = name;
this.context = FacadeFactory.sourcesContext.createChildContext(name);
}
private final DefaultListFacade<CampaignFacade> campaigns =
new DefaultListFacade<>();
private final WriteableReferenceFacade<GameModeFacade> gameModeRef =
new DefaultReferenceFacade<>();
@Override
public boolean isModifiable()
{
return true;
}
@Override
public void setCampaigns(List<CampaignFacade> campaign)
{
campaigns.setContents(campaign);
List<String> camps = new ArrayList<>();
for (CampaignFacade camp : campaign)
{
camps.add(camp.getName());
}
context.setStringArray("campaigns", camps);
}
@Override
public void setGameMode(GameModeFacade gameMode)
{
gameModeRef.set(gameMode);
context.setProperty("gamemode", gameMode.getName());
}
@Override
public String toString()
{
return name;
}
@Override
public LoadingState getLoadingState()
{
return loadingState;
}
@Override
public String getLoadingErrorMessage()
{
return errorMessage;
}
private void setLoadingState(LoadingState loadingState)
{
this.loadingState = loadingState;
}
private void setErrorMessage(String errorMessage)
{
this.errorMessage = errorMessage;
}
@Override
public ListFacade<CampaignFacade> getCampaigns()
{
return campaigns;
}
@Override
public ReferenceFacade<GameModeFacade> getGameMode()
{
return gameModeRef;
}
}
}