/* * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.jtrac.domain; import static info.jtrac.Constants.*; import info.jtrac.util.XmlUtils; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.dom4j.Element; /** * <code>Metadata</code> is composited of Field elements * that represent each of the custom fields that may be * used within an item */ public class Field implements Serializable { private Name name; private String label; private boolean optional; private Map<String, String> options; private static final Map<String, Name> NAMES_MAP; // set up a static Map to resolve a String to our Field.Name enum value static { NAMES_MAP = new HashMap<String, Name>(); for (Name n : Name.values()) { NAMES_MAP.put(n.text, n); } } /** * Resolve a String to a valid enum value for Field.Name */ public static Name convertToName(String text) { Name n = NAMES_MAP.get(text); if (n == null) { throw new RuntimeException("Bad name " + text); } return n; } /** * test if a given string is a valid field name */ public static boolean isValidName(String text) { return NAMES_MAP.containsKey(text); } /** * the names that are used for the custom fields in the outside * world - e.g. the XML representation of the metadata that is * persisted to the database */ public enum Name { SEVERITY (1, "severity"), PRIORITY (2, "priority"), CUS_INT_01 (3, "cusInt01"), CUS_INT_02 (3, "cusInt02"), CUS_INT_03 (3, "cusInt03"), CUS_INT_04 (3, "cusInt04"), CUS_INT_05 (3, "cusInt05"), CUS_INT_06 (3, "cusInt06"), CUS_INT_07 (3, "cusInt07"), CUS_INT_08 (3, "cusInt08"), CUS_INT_09 (3, "cusInt09"), CUS_INT_10 (3, "cusInt10"), CUS_DBL_01 (4, "cusDbl01"), CUS_DBL_02 (4, "cusDbl02"), CUS_DBL_03 (4, "cusDbl03"), CUS_STR_01 (5, "cusStr01"), CUS_STR_02 (5, "cusStr02"), CUS_STR_03 (5, "cusStr03"), CUS_STR_04 (5, "cusStr04"), CUS_STR_05 (5, "cusStr05"), CUS_TIM_01 (6, "cusTim01"), CUS_TIM_02 (6, "cusTim02"), CUS_TIM_03 (6, "cusTim03"); private final int type; private final String text; Name(int type, String text) { this.type = type; this.text = text; } public int getType() { return type; } public String getText() { return text; } public boolean isDropDownType() { return type < 4; } public String getDescription() { switch (type) { case 1: return "Severity (Drop Down)"; case 2: return "Priority (Drop Down)"; case 3: return "Drop Down List"; case 4: return "Decimal Number"; case 5: return "Free Text Field"; case 6: return "Date Field"; default: throw new RuntimeException("Unknown type " + type); } } @Override public String toString() { return text; } } //=================================================================== public Field() { // zero arg constructor } public Field(String fieldName) { this.setName(fieldName); } public Field(Name n) { this.setName(n); } public Field(Element e) { setName(e.attributeValue(NAME)); label = e.attributeValue(LABEL); if (e.attribute(OPTIONAL) != null && e.attributeValue(OPTIONAL).equals(TRUE)) { optional = true; } for (Object o : e.elements(OPTION)) { addOption((Element) o); } } /* append this object onto an existing XML document */ public void addAsChildOf(Element parent) { Element e = parent.addElement(FIELD); copyTo(e); } /* marshal this object into a fresh new XML Element */ public Element getAsElement() { Element e = XmlUtils.getNewElement(FIELD); copyTo(e); return e; } /* copy object values into an existing XML Element */ private void copyTo(Element e) { // appending empty strings to create new objects for "clone" support e.addAttribute(NAME, name + ""); e.addAttribute(LABEL, label + ""); if (optional) { e.addAttribute(OPTIONAL, TRUE); } if (options == null) { return; } for (Map.Entry<String, String> entry : options.entrySet()) { Element option = e.addElement(OPTION); option.addAttribute(VALUE, entry.getKey() + ""); option.addText((String) entry.getValue() + ""); } } public void addOption(String value) { if (options == null) { addOption("1", value); return; } Set<Integer> set = new TreeSet<Integer>(); for (String s : options.keySet()) { set.add(new Integer(s)); } int last = set.toArray(new Integer[set.size()])[set.size() -1]; addOption(last + 1 + "", value); } public void addOption(String key, String value) { if (options == null) { options = new LinkedHashMap<String, String>(); } options.put(key, value); } public void addOption(Element e) { String value = e.attributeValue(VALUE); if (value == null) { return; } String text = e.getTextTrim(); if (text == null || text.equals("")) { return; } addOption(value, text); } public String getCustomValue(String key) { if (options == null || key == null) { return ""; } String value = options.get(key); if (value == null) { return ""; } return value; } public boolean hasOption(String value) { if (options == null) { return false; } return options.containsValue(value); } public Field getClone() { return new Field(getAsElement()); } public void initOptions() { // TODO i18n if (name.type == 1) { label = "Severity"; addOption("1", "Fatal"); addOption("2", "Major"); addOption("3", "Minor"); addOption("4", "Trivial"); addOption("5", "Suggestion"); } else if (name.type == 2) { label = "Priority"; addOption("1", "Highest"); addOption("2", "High"); addOption("3", "Medium"); addOption("4", "Low"); addOption("5", "Lowest"); } } /* custom accessor */ public void setName(String nameAsString) { setName(convertToName(nameAsString)); } public boolean isDropDownType() { return name.isDropDownType(); } public boolean isDatePickerType() { return name.type == 6; } public boolean isDecimalNumberType() { return name.type == 4; } public Map<Integer, String> getOptionsWithIntegerKeys() { Map<Integer, String> map = new HashMap<Integer, String>(options.size()); for(Map.Entry<String, String> entry : options.entrySet()) { map.put(new Integer(entry.getKey()), entry.getValue()); } return map; } //=================================================================== public Map<String, String> getOptions() { return options; } public void setOptions(Map<String, String> options) { this.options = options; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public boolean isOptional() { return optional; } public void setOptional(boolean optional) { this.optional = optional; } public Name getName() { return name; } public void setName(Name name) { this.name = name; } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("name [").append(name); sb.append("]; label [").append(label); sb.append("]; optional [").append(optional); sb.append("]; options [").append(options); sb.append("]"); return sb.toString(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Field)) { return false; } final Field f = (Field) o; return f.getName().equals(name); } @Override public int hashCode() { if (name == null) { return 0; } return name.hashCode(); } }