/* * Copyright (C) 2016 MegaMek team * * This file is part of MekHQ. * * MekHQ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MekHQ 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MekHQ. If not, see <http://www.gnu.org/licenses/>. */ package mekhq.campaign.personnel; import java.util.Arrays; import java.util.EnumSet; import java.util.HashSet; import java.util.Locale; import java.util.Set; import javax.xml.bind.annotation.adapters.XmlAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlJavaTypeAdapter(BodyLocation.XMLAdapter.class) public enum BodyLocation { HEAD(0, "head"), LEFT_LEG(1, "left leg", true), LEFT_ARM(2, "left arm", true), CHEST(3, "chest"), ABDOMEN(4, "abdomen"), RIGHT_ARM(5, "right arm", true), RIGHT_LEG(6, "right leg", true), INTERNAL(7, "innards"), LEFT_HAND(8, "left hand", true, LEFT_ARM), RIGHT_HAND(9, "right hand", true, RIGHT_ARM), LEFT_FOOT(10, "left foot", true, LEFT_LEG), RIGHT_FOOT(11, "right foot", true, RIGHT_LEG), GENERIC(-1, ""); // Initialize by-id array lookup table private static BodyLocation[] idMap; static { int maxId = 0; for(BodyLocation workTime : values()) { maxId = Math.max(maxId, workTime.id); } idMap = new BodyLocation[maxId + 1]; Arrays.fill(idMap, GENERIC); for(BodyLocation workTime : values()) { if(workTime.id > 0) { idMap[workTime.id] = workTime; } // Optimise the children sets (we can't do that in the constructor, since // the EnumSet static methods require this enum to be fully initialized first). if(workTime.children.isEmpty()) { workTime.children = EnumSet.noneOf(BodyLocation.class); } else { workTime.children = EnumSet.copyOf(workTime.children); } } } /** @return the body location corresponding to the (old) ID */ public static BodyLocation of(int id) { return ((id > 0) && (id < idMap.length)) ? idMap[id] : GENERIC; } /** @return the body location corresponding to the given string */ public static BodyLocation of(String str) { try { return of(Integer.valueOf(str)); } catch(NumberFormatException nfex) { // Try something else } return valueOf(str.toUpperCase(Locale.ROOT)); } public final int id; // Includes everything attached to a limb public final boolean isLimb; public final String readableName; public final BodyLocation parent; // We can't use an EnumSet here because it requires the whole enum to be initialised. We // fix it later, in the static code block. private Set<BodyLocation> children = new HashSet<>(); private BodyLocation(int id, String readableName) { this(id, readableName, false, null); } private BodyLocation(int id, String readableName, boolean isLimb) { this(id, readableName, isLimb, null); } private BodyLocation(int id, String readableName, boolean isLimb, BodyLocation parent) { this.id = id; this.readableName = readableName; this.isLimb = isLimb; this.parent = parent; if(null != parent) { parent.addChildLocation(this); } } private void addChildLocation(BodyLocation child) { children.add(child); } public boolean isParentOf(BodyLocation child) { if(children.contains(child)) { return true; } for(BodyLocation myChild : children) { if(myChild.isParentOf(child)) { return true; } } return false; } public boolean isChildOf(BodyLocation parent) { return (null != this.parent) ? (this.parent == parent) || this.parent.isChildOf(parent) : false; } public static final class XMLAdapter extends XmlAdapter<String, BodyLocation> { @Override public BodyLocation unmarshal(String v) throws Exception { return (null == v) ? null : BodyLocation.of(v); } @Override public String marshal(BodyLocation v) throws Exception { return (null == v) ? null : v.toString(); } } }