All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.rpgframework.genericrpg.data.ComplexDataItem Maven / Gradle / Ivy

package de.rpgframework.genericrpg.data;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;

import org.prelle.simplepersist.Attribute;
import org.prelle.simplepersist.Element;
import org.prelle.simplepersist.ElementList;

import de.rpgframework.HasName;
import de.rpgframework.genericrpg.items.ItemFlag;
import de.rpgframework.genericrpg.items.PieceOfGearVariant;
import de.rpgframework.genericrpg.modification.DataItemModification;
import de.rpgframework.genericrpg.modification.Modification;
import de.rpgframework.genericrpg.modification.ModificationChoice;
import de.rpgframework.genericrpg.modification.ModificationList;
import de.rpgframework.genericrpg.modification.ModifiedObjectType;
import de.rpgframework.genericrpg.requirements.Requirement;
import de.rpgframework.genericrpg.requirements.RequirementList;

/**
 * @author prelle
 *
 */
public class ComplexDataItem extends DataItem implements ChoiceOrigin {

	/**
	 * When instantiating an entity of this item, the following choices must
	 * be presented to the user.
	 */
	@ElementList(type = Choice.class, entry = "choice")
	protected List choices;
	@Element
	protected ModificationList modifications;
	@Element
	protected RequirementList requires;

	@Attribute(name="hasLevel")
	protected boolean hasLevel;

	/**
	 * These flags can be freely selected by a user
	 */
	@ElementList(entry = "flag", type = String.class, inline = false)
	protected List userSelectableFlags;

	//-------------------------------------------------------------------
	/**
	 */
	public ComplexDataItem() {
		choices = new ArrayList<>();
		modifications = new ModificationList();
		requires = new RequirementList();
	}

	//-------------------------------------------------------------------
	public List getChoices() {
		return new ArrayList(choices);
	}

	//-------------------------------------------------------------------
	public void addChoice(Choice choice) {
		if (!choices.contains(choice))
			choices.add(choice);
	}

	//-------------------------------------------------------------------
	/**
	 * @see de.rpgframework.genericrpg.data.ChoiceOrigin#getChoice(java.util.UUID)
	 */
	@Override
	public Choice getChoice(UUID uuid) {
		if (choices!=null) {
			for (Choice choice : choices) {
				if (choice.uuid==null || choice.uuid.equals(uuid))
					return choice;
			}
		}
		return null;
	}

	//-------------------------------------------------------------------
	public Choice getChoice(String ref) {
		if (choices!=null) {
			for (Choice choice : choices) {
				if (choice.ref!=null && choice.ref.equals(ref))
					return choice;
			}
		}
		return null;
	}

	//-------------------------------------------------------------------
	public Choice getChoice(ModifiedObjectType type) {
		if (choices!=null) {
			for (Choice choice : choices) {
				if (choice.type==type)
					return choice;
			}
		}
		return null;
	}

	//-------------------------------------------------------------------
	public ModificationChoice getModificationChoice(UUID uuid) {
		for (Modification tmp : modifications) {
			if (tmp instanceof ModificationChoice && ((ModificationChoice)tmp).getUUID().equals(uuid))
				return (ModificationChoice)tmp;
		}
		return null;
	}

	//-------------------------------------------------------------------
	/**
	 * Override by specific implements (like AUGMENTATION_QUALITY fo SR6)
	 */
	protected Choice getHardcodedChoice(UUID uuid) {
		return null;
	}

	//-------------------------------------------------------------------
	public List getOutgoingModifications() {
		return new ArrayList(modifications);
	}

	//-------------------------------------------------------------------
	public void addOutgoingModifications(List value) {
		this.modifications.addAll(value);
	}

	//-------------------------------------------------------------------
	public List getRequirements() {
		return requires;
	}

	//-------------------------------------------------------------------
	public boolean hasLevel() {
		return hasLevel;
	}

	//-------------------------------------------------------------------
	public void setHasLevel(boolean hasLevel) {
		this.hasLevel = hasLevel;
	}

	//-------------------------------------------------------------------
	/**
	 * Used in deriving classes to perform validation checks on loading,
	 * if necessary
	 * @return Error message or NULL
	 */
	public void validate() throws DataErrorException {
		super.validate();
		for (Modification tmp : modifications) {
			tmp.setSource(this);
		}
		// Validate modifications
		try {
			modifications.validate();
		} catch (ReferenceException e) {
			e.printStackTrace();
			throw new DataErrorException(this, e.getError());
		}
		// Validate decisions in modifications
		for (Modification tmp : modifications) {
			if (tmp instanceof DataItemModification) {
				DataItemModification mod = (DataItemModification)tmp;
				Object resolved = null;
				if (mod.getKey().startsWith("CHOICE:")) {
					try {
						String uuid_s = mod.getKey().substring(7);
						UUID uuid = UUID.fromString(uuid_s);
					} catch (Exception e) {
						throw new DataErrorException(this, "Referring to decision must be 'CHOICE:'");
					}
				}
				if (!"CHOICE".equals(mod.getKey()) && !mod.getKey().startsWith("CHOICE:")) {
					resolved = mod.getReferenceType().resolve(mod.getKey());
				}
				ComplexDataItem item = (resolved instanceof ComplexDataItem)?(ComplexDataItem) resolved:null;
				// Validate decisions
				for (Decision dec : mod.getDecisions()) {
					if (dec.getValue()!=null && dec.getValue().length()<3)
						continue;
					UUID uuid = dec.getChoiceUUID();
					Choice choice = getChoice(uuid);
					if (choice==null && item!=null)
						choice = item.getChoice(uuid);
					if (choice==null)
						throw new DataErrorException(this, "Decision for non-existing choice "+uuid+" in item "+item);
					// Before resolving, check if the reference is a UUID
					try {
						dec.setValueAsUUID( UUID.fromString(dec.getValue()) );
						continue;
					} catch (Exception e) {
					}
					resolved = choice.getChooseFrom().resolve(dec.getValue());
					if (resolved==null) {
						throw new ReferenceException(choice.getChooseFrom(), dec.getValue(), this);
					}
				}

			}
		}

		// Validate requirements
		try {
			requires.validate();
		} catch (ReferenceException e) {
			throw new DataErrorException(this, e.getError());
		}


		// Choices in modifications must match available choices
		for (Modification tmp : modifications) {
			if (parentItem!=null)
				tmp.setSource(parentItem);
			else
				tmp.setSource(this);
			if (tmp instanceof DataItemModification) {
				DataItemModification mod = (DataItemModification)tmp;
				if ("CHOICE".equals(((DataItemModification) tmp).getKey())) {
					// Is there a UUID for a choice given?
					if (mod.getConnectedChoice()==null)
						throw new DataErrorException(this, "Missing choice=\"\"");
					// Is the UUID a valid choice UUID?
					Choice choice = getChoice(mod.getConnectedChoice());
					if (choice==null)
						throw new DataErrorException(this, "No such choice "+mod.getConnectedChoice());
					// Does the modification type match the choice type?
					if (choice.getChooseFrom()!=mod.getReferenceType())
						throw new DataErrorException(this, "Modification type "+mod.getReferenceType()+" does not match choice type "+choice.getChooseFrom());
				}
			}
		}

		// Choices
		for (Choice tmp : choices) {
			if (tmp.getChoiceOptions()!=null && tmp.getChoiceOptions().length>0) {
				if (tmp.getTypeReference()==null)
					tmp.setTypeReference("CHOICE");
//				if (!tmp.getTypeReference().equals("CHOICE")) {
//					throw new DataErrorException(this, "Choice "+tmp.getUUID()+" has options, so it should have ref=\"CHOICE\"");
//				}
			}
			getChoiceName(tmp, Locale.getDefault());
			if (!"SUBSELECT".equals(tmp.getChooseFrom().toString()))
				continue;
			String key = getTypeString()+"."+id.toLowerCase()+".choice."+tmp.ref.toLowerCase();
			getLocalizedString(Locale.getDefault(), key);
			for (ChoiceOption opt : tmp.getSubOptions()) {
				opt.parentSet = this.parentSet;
				opt.parent = this;
				opt.choice = tmp;
				getLocalizedString(Locale.getDefault(), key+"."+opt.getId());
				getLocalizedString(Locale.getDefault(), key+"."+opt.getId()+".desc");
				for (Modification m : opt.getOutgoingModifications()) {
					m.setSource(this);
					m.validate();
				}
			}
		}
	}

	//-------------------------------------------------------------------
	public void resolveWithinItem(Modification m) {

	}

	//-------------------------------------------------------------------
	public String getChoiceName(Choice choice, Locale loc) {
		List keys = new ArrayList();
		if (choice==null && hasLevel) {
			keys.add("choice.rating");
		}
		if (choice==null || choice.getChooseFrom()==null)
			return "";
		if (choice!=null && choice.getI18nKey()!=null)
			keys.add("choice."+choice.getI18nKey());
		String itemID   = getTypeString()+"."+id.toLowerCase();
		String parentID = (parentItem!=null)?(parentItem.getTypeString()+"."+parentItem.id.toLowerCase()):null;
		String typeID   = "choice."+String.valueOf(choice.getChooseFrom()).toLowerCase();
		String choiceID = (choice.getTypeReference()!=null)?("choice."+choice.getTypeReference().toLowerCase()):"?";
		if (choice.getTypeReference()!=null && choice.getTypeReference().equals("CHOICE"))
			choiceID = String.valueOf(choice.getUUID());

		if (parentItem!=null) {
			keys.add(parentID+"."+itemID+"."+typeID+"."+choiceID);
			keys.add(parentID+"."+itemID+"."+typeID);
			keys.add(parentID+"."+itemID+"."+choiceID);
			keys.add(parentID+"."+choiceID);

		}
		keys.add(itemID+"."+typeID+"."+choiceID);
		keys.add(           typeID+"."+choiceID);
		keys.add(itemID+"."+typeID);
		keys.add(           typeID);
		keys.add(itemID+"."+choiceID);
		keys.add(           choiceID);

		return getLocalizedString(loc, keys);
	}

	//-------------------------------------------------------------------
	public String getVariantName(PieceOfGearVariant variant, Locale loc) {
		String key = getTypeString()+"."+id.toLowerCase();
		key+=".variant."+variant.getId();
		if (variant.getGlobalI18NKey()!=null)
			key = variant.getGlobalI18NKey();

		return getLocalizedString(loc, key);
	}

	//-------------------------------------------------------------------
	/**
	 * @param choice
	 * @param opt
	 * @param loc
	 * @return 0=Option name, 1=Option description
	 */
	public String[] getChoiceOptionStrings(Choice choice, ChoiceOption opt, Locale loc) {
		if (opt==null)
			throw new NullPointerException("ChoiceOption is null");
		String key = getTypeString()+"."+id.toLowerCase()+".choice."+choice.ref.toLowerCase();
		return new String[] {
				getLocalizedString(loc, key+"."+opt.getId()),
				getLocalizedString(loc, key+"."+opt.getId()+".desc")
				};
	}

	//-------------------------------------------------------------------
	public String getChoiceOptionString(Choice choice, HasName opt, Locale loc) {
		if (opt==null)
			throw new NullPointerException("ChoiceOption is null");
		String key = getTypeString()+"."+id.toLowerCase()+".choice.";
		if (choice.ref!=null)
			key+=choice.ref.toLowerCase();
		return getLocalizedString(loc, key+"."+opt.getId());
	}

	//-------------------------------------------------------------------
	//@SuppressWarnings({ "unchecked", "rawtypes" })
	public  List getUserSelectableFlags(Class cls) {
		List ret = new ArrayList<>();
		for (String s : userSelectableFlags) {
			T tmp = (T) Enum.valueOf(cls, s);
			ret.add(tmp);
		}
		return ret;
//		return userSelectableFlags.stream().map(s -> Enum.valueOf(cls, s)).collect(Collectors.toList());
	}

	//-------------------------------------------------------------------
	public boolean hasUserSelectableFlag(ItemFlag flag) {
		return userSelectableFlags.contains(flag.name());
	}

	//-------------------------------------------------------------------
	public void addUserSelectableFlag(ItemFlag flag) {
		if (!userSelectableFlags.contains(flag.name()))
			this.userSelectableFlags.add(flag.name());
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy