/**
* DescriptionFacadeImpl.java
* Copyright James Dempsey, 2011
*
* 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 06/10/2011 7:59:35 PM
*
* $Id$
*/
package pcgen.gui2.facade;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import pcgen.cdom.enumeration.BiographyField;
import pcgen.cdom.enumeration.PCStringKey;
import pcgen.core.ChronicleEntry;
import pcgen.core.NoteItem;
import pcgen.cdom.enumeration.NotePCAttribute;
import pcgen.core.PlayerCharacter;
import pcgen.core.display.CharacterDisplay;
import pcgen.facade.core.ChronicleEntryFacade;
import pcgen.facade.core.DescriptionFacade;
import pcgen.facade.core.NoteFacade;
import pcgen.facade.util.DefaultListFacade;
import pcgen.facade.util.DefaultReferenceFacade;
import pcgen.facade.util.ListFacade;
import pcgen.facade.util.ReferenceFacade;
import pcgen.facade.util.WriteableReferenceFacade;
import pcgen.system.LanguageBundle;
/**
* The Class {@code DescriptionFacadeImpl} is an implementation of
* the DescriptionFacade interface for the new user interface. It is
* intended to provide a full implementation of the new ui/core
* interaction layer.
*
* @author James Dempsey <jdempsey@users.sourceforge.net>
*/
class DescriptionFacadeImpl implements DescriptionFacade
{
/** Name of the Biography node. */
private static final String NOTE_NAME_BIO = LanguageBundle
.getString("in_bio"); //$NON-NLS-1$
/** Name of the Description node. */
private static final String NOTE_NAME_DESCRIP = LanguageBundle
.getString("in_descrip"); //$NON-NLS-1$
/** Name of the Companions notes node. */
private static final String NOTE_NAME_COMPANION = LanguageBundle
.getString("in_companions"); //$NON-NLS-1$
/** Name of the Other Assets notes node. */
private static final String NOTE_NAME_OTHER_ASSETS = LanguageBundle
.getString("in_otherAssets"); //$NON-NLS-1$
/** Name of the Magic Item notes node. */
private static final String NOTE_NAME_MAGIC_ITEMS = LanguageBundle
.getString("in_magicItems"); //$NON-NLS-1$
/** Name of the DM Notes node. */
private static final String NOTE_NAME_GM_NOTES = LanguageBundle
.getString("in_gmNotes"); //$NON-NLS-1$
private final PlayerCharacter theCharacter;
private final CharacterDisplay charDisplay;
private final DefaultListFacade<ChronicleEntryFacade> chronicleEntries;
private DefaultListFacade<NoteFacade> notes;
private Map<BiographyField, WriteableReferenceFacade<String>> bioData = new EnumMap<>(BiographyField.class);
private final DefaultListFacade<BiographyField> customBiographyFields;
private static DefaultReferenceFacade<String> newDefaultBioFieldFor(final PlayerCharacter pc, final PCStringKey key)
{
return new DefaultReferenceFacade<>(pc.getDisplay().getSafeStringFor(key));
}
/**
* Create a new DescriptionFacadeImpl instance for the character.
* @param pc The character.
*/
DescriptionFacadeImpl(PlayerCharacter pc)
{
theCharacter = pc;
charDisplay = pc.getDisplay();
chronicleEntries = new DefaultListFacade<>();
charDisplay.getChronicleEntries().forEach(chronicleEntries::addElement);
notes = new DefaultListFacade<>();
addDefaultNotes();
charDisplay.getNotesList().forEach(item ->
notes.addElement(item));
bioData.put(BiographyField.BIRTHDAY, DescriptionFacadeImpl.newDefaultBioFieldFor(pc, PCStringKey.BIRTHDAY));
bioData.put(BiographyField.BIRTHPLACE, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.BIRTHPLACE)));
bioData.put(BiographyField.LOCATION, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.LOCATION)));
bioData.put(BiographyField.CITY, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.RESIDENCE)));
bioData.put(BiographyField.REGION, new DefaultReferenceFacade<>(charDisplay.getRegionString()));
bioData.put(BiographyField.PERSONALITY_TRAIT_1, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.PERSONALITY1)));
bioData.put(BiographyField.PERSONALITY_TRAIT_2, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.PERSONALITY2)));
bioData.put(BiographyField.PHOBIAS, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.PHOBIAS)));
bioData.put(BiographyField.INTERESTS, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.INTERESTS)));
bioData.put(BiographyField.CATCH_PHRASE, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.CATCHPHRASE)));
bioData.put(BiographyField.HAIR_STYLE, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.HAIRSTYLE)));
bioData.put(BiographyField.SPEECH_PATTERN, new DefaultReferenceFacade<>(charDisplay.getSafeStringFor(PCStringKey.SPEECHTENDENCY)));
customBiographyFields = new DefaultListFacade<>();
addCharacterCustomFields();
}
private void addDefaultNotes()
{
notes.addElement(createDefaultNote(NOTE_NAME_BIO, charDisplay.getBio()));
notes.addElement(createDefaultNote(NOTE_NAME_DESCRIP, charDisplay.getSafeStringFor(PCStringKey.DESCRIPTION)));
notes.addElement(createDefaultNote(NOTE_NAME_COMPANION,
charDisplay.getSafeStringFor(PCStringKey.COMPANIONS)));
notes.addElement(createDefaultNote(NOTE_NAME_OTHER_ASSETS,
charDisplay.getSafeStringFor(PCStringKey.ASSETS)));
notes.addElement(createDefaultNote(NOTE_NAME_MAGIC_ITEMS,
charDisplay.getSafeStringFor(PCStringKey.MAGIC)));
notes.addElement(createDefaultNote(NOTE_NAME_GM_NOTES,
charDisplay.getSafeStringFor(PCStringKey.GMNOTES)));
}
/**
* @param noteName
* @param value
* @return
*/
private NoteFacade createDefaultNote(String noteName, String value)
{
NoteItem note = new NoteItem(0, -1, noteName, value);
note.setRequired(true);
return note;
}
/**
* Add any custom biography fields already registered for the character.
*/
private void addCharacterCustomFields()
{
for (BiographyField field : EnumSet.range(BiographyField.SPEECH_PATTERN, BiographyField.CATCH_PHRASE))
{
if (StringUtils.isNotEmpty(getBiographyField(field).get()))
{
customBiographyFields.addElement(field);
}
}
}
/* (non-Javadoc)
* @see pcgen.core.facade.DescriptionFacade#createChronicleEntry()
*/
@Override
public ChronicleEntryFacade createChronicleEntry()
{
ChronicleEntry chronicleEntry = new ChronicleEntry();
theCharacter.addChronicleEntry(chronicleEntry);
chronicleEntries.addElement(chronicleEntry);
return chronicleEntry;
}
/* (non-Javadoc)
* @see pcgen.core.facade.DescriptionFacade#removeChronicleEntry(pcgen.core.ChronicleEntry)
*/
@Override
public void removeChronicleEntry(ChronicleEntryFacade chronicleEntry)
{
if (chronicleEntry instanceof ChronicleEntry)
{
theCharacter.removeChronicleEntry((ChronicleEntry) chronicleEntry);
}
chronicleEntries.removeElement(chronicleEntry);
}
/* (non-Javadoc)
* @see pcgen.core.facade.DescriptionFacade#getChronicleEntries()
*/
@Override
public ListFacade<ChronicleEntryFacade> getChronicleEntries()
{
return chronicleEntries;
}
@Override
public ListFacade<NoteFacade> getNotes()
{
return notes;
}
@Override
public void setNote(NoteFacade note, String text)
{
if (!(note instanceof NoteItem))
{
return;
}
NoteItem noteItem = (NoteItem) note;
noteItem.setValue(text);
if (noteItem.isRequired())
{
String noteName = noteItem.getName();
NotePCAttribute whichAttr = NotePCAttribute.getByNoteName(noteName);
theCharacter.setPCAttribute(whichAttr, text);
}
}
@Override
public void renameNote(NoteFacade note, String newName)
{
if (!(note instanceof NoteItem) || note.isRequired())
{
return;
}
NoteItem noteItem = (NoteItem) note;
noteItem.setName(newName);
notes.modifyElement(noteItem);
}
@Override
public void deleteNote(NoteFacade note)
{
if (!(note instanceof NoteItem) || note.isRequired())
{
return;
}
theCharacter.removeNote((NoteItem) note);
notes.removeElement(note);
}
@Override
public void addNewNote()
{
int parentId = -1;
int newNodeId = 0;
for (NoteItem currItem : charDisplay.getNotesList())
{
if (currItem.getId() > newNodeId)
{
newNodeId = currItem.getId();
}
}
++newNodeId;
Set<String> names = new HashSet<>();
for (NoteFacade note : notes)
{
names.add(note.getName());
}
String baseName = LanguageBundle.getString("in_newItem"); //$NON-NLS-1$
String name = baseName;
int num = 0;
while (names.contains(name))
{
num++;
name = baseName + " " + num; //$NON-NLS-1$
}
NoteItem note =
new NoteItem(newNodeId, parentId, name, LanguageBundle
.getString("in_newValue")); //$NON-NLS-1$
theCharacter.addNotesItem(note);
notes.addElement(note);
}
@Override
public ReferenceFacade<String> getBiographyField(final BiographyField field)
{
if (bioData.containsKey(field))
{
return bioData.get(field);
}
throw new UnsupportedOperationException("The field " + field //$NON-NLS-1$
+ " must use a dedicated getter."); //$NON-NLS-1$
}
@Override
public void setBiographyField(final BiographyField field, final String newValue)
{
// TODO: generify this
Set<BiographyField> canBeDirectlySet = EnumSet.of(
BiographyField.LOCATION,
BiographyField.SPEECH_PATTERN,
BiographyField.INTERESTS,
BiographyField.BIRTHPLACE,
BiographyField.PERSONALITY_TRAIT_1,
BiographyField.PERSONALITY_TRAIT_2,
BiographyField.CITY,
BiographyField.PHOBIAS,
BiographyField.CATCH_PHRASE,
BiographyField.HAIR_STYLE,
BiographyField.BIRTHDAY
);
if (canBeDirectlySet.contains(field))
{
bioData.get(field).set(newValue);
theCharacter.setPCAttribute(field.getPcattr(), newValue);
}
else if (field == BiographyField.REGION)
{
throw new UnsupportedOperationException("The field " + field //$NON-NLS-1$
+ " cannot be set from the UI."); //$NON-NLS-1$
}
else
{
throw new UnsupportedOperationException("The field " + field //$NON-NLS-1$
+ " must use a dedicated setter."); //$NON-NLS-1$
}
}
@Override
public ListFacade<BiographyField> getCustomBiographyFields()
{
return customBiographyFields;
}
@Override
public void addCustomBiographyField(BiographyField field)
{
customBiographyFields.addElement(field);
}
@Override
public void removeCustomBiographyField(BiographyField field)
{
customBiographyFields.removeElement(field);
}
}