001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package info.jtrac.domain;
018:
019: import static info.jtrac.Constants.*;
020:
021: import info.jtrac.util.XmlUtils;
022:
023: import java.io.Serializable;
024: import java.util.HashMap;
025: import java.util.LinkedHashMap;
026: import java.util.Map;
027: import java.util.Set;
028: import java.util.TreeSet;
029:
030: import org.dom4j.Element;
031:
032: /**
033: * <code>Metadata</code> is composited of Field elements
034: * that represent each of the custom fields that may be
035: * used within an item
036: */
037: public class Field implements Serializable {
038:
039: private Name name;
040: private String label;
041: private boolean optional;
042: private Map<String, String> options;
043:
044: private static final Map<String, Name> NAMES_MAP;
045:
046: // set up a static Map to resolve a String to our Field.Name enum value
047: static {
048: NAMES_MAP = new HashMap<String, Name>();
049: for (Name n : Name.values()) {
050: NAMES_MAP.put(n.text, n);
051: }
052: }
053:
054: /**
055: * Resolve a String to a valid enum value for Field.Name
056: */
057: public static Name convertToName(String text) {
058: Name n = NAMES_MAP.get(text);
059: if (n == null) {
060: throw new RuntimeException("Bad name " + text);
061: }
062: return n;
063: }
064:
065: /**
066: * the names that are used for the custom fields in the outside
067: * world - e.g. the XML representation of the metadata that is
068: * persisted to the database
069: */
070: public enum Name {
071: SEVERITY(1, "severity"), PRIORITY(2, "priority"), CUS_INT_01(3,
072: "cusInt01"), CUS_INT_02(3, "cusInt02"), CUS_INT_03(3,
073: "cusInt03"), CUS_INT_04(3, "cusInt04"), CUS_INT_05(3,
074: "cusInt05"), CUS_INT_06(3, "cusInt06"), CUS_INT_07(3,
075: "cusInt07"), CUS_INT_08(3, "cusInt08"), CUS_INT_09(3,
076: "cusInt09"), CUS_INT_10(3, "cusInt10"), CUS_DBL_01(4,
077: "cusDbl01"), CUS_DBL_02(4, "cusDbl02"), CUS_DBL_03(4,
078: "cusDbl03"), CUS_STR_01(5, "cusStr01"), CUS_STR_02(5,
079: "cusStr02"), CUS_STR_03(5, "cusStr03"), CUS_STR_04(5,
080: "cusStr04"), CUS_STR_05(5, "cusStr05"), CUS_TIM_01(6,
081: "cusTim01"), CUS_TIM_02(6, "cusTim02"), CUS_TIM_03(6,
082: "cusTim03");
083:
084: private final int type;
085: private final String text;
086:
087: Name(int type, String text) {
088: this .type = type;
089: this .text = text;
090: }
091:
092: public int getType() {
093: return type;
094: }
095:
096: public String getText() {
097: return text;
098: }
099:
100: public String getDescription() {
101: switch (type) {
102: case 1:
103: return "Severity (Drop Down)";
104: case 2:
105: return "Priority (Drop Down)";
106: case 3:
107: return "Drop Down List";
108: case 4:
109: return "Decimal Number";
110: case 5:
111: return "Free Text Field";
112: case 6:
113: return "Date Field";
114: default:
115: throw new RuntimeException("Unknown type " + type);
116: }
117: }
118:
119: @Override
120: public String toString() {
121: return text;
122: }
123: }
124:
125: //===================================================================
126:
127: public Field() {
128: // zero arg constructor
129: }
130:
131: public Field(String fieldName) {
132: this .setName(fieldName);
133: }
134:
135: public Field(Name n) {
136: this .setName(n);
137: }
138:
139: public Field(Element e) {
140: setName(e.attributeValue(NAME));
141: label = e.attributeValue(LABEL);
142: if (e.attribute(OPTIONAL) != null
143: && e.attributeValue(OPTIONAL).equals(TRUE)) {
144: optional = true;
145: }
146: for (Object o : e.elements(OPTION)) {
147: addOption((Element) o);
148: }
149: }
150:
151: /* append this object onto an existing XML document */
152: public void addAsChildOf(Element parent) {
153: Element e = parent.addElement(FIELD);
154: copyTo(e);
155: }
156:
157: /* marshal this object into a fresh new XML Element */
158: public Element getAsElement() {
159: Element e = XmlUtils.getNewElement(FIELD);
160: copyTo(e);
161: return e;
162: }
163:
164: /* copy object values into an existing XML Element */
165: private void copyTo(Element e) {
166: // appending empty strings to create new objects for "clone" support
167: e.addAttribute(NAME, name + "");
168: e.addAttribute(LABEL, label + "");
169: if (optional) {
170: e.addAttribute(OPTIONAL, TRUE);
171: }
172: if (options == null) {
173: return;
174: }
175: for (Map.Entry<String, String> entry : options.entrySet()) {
176: Element option = e.addElement(OPTION);
177: option.addAttribute(VALUE, entry.getKey() + "");
178: option.addText((String) entry.getValue() + "");
179: }
180: }
181:
182: public void addOption(String value) {
183: if (options == null) {
184: addOption("1", value);
185: return;
186: }
187: Set<Integer> set = new TreeSet<Integer>();
188: for (String s : options.keySet()) {
189: set.add(new Integer(s));
190: }
191: int last = set.toArray(new Integer[set.size()])[set.size() - 1];
192: addOption(last + 1 + "", value);
193: }
194:
195: public void addOption(String key, String value) {
196: if (options == null) {
197: options = new LinkedHashMap<String, String>();
198: }
199: options.put(key, value);
200: }
201:
202: public void addOption(Element e) {
203: String value = e.attributeValue(VALUE);
204: if (value == null) {
205: return;
206: }
207: String text = e.getTextTrim();
208: if (text == null || text.equals("")) {
209: return;
210: }
211: addOption(value, text);
212: }
213:
214: public String getCustomValue(String key) {
215: if (options == null || key == null) {
216: return "";
217: }
218: String value = options.get(key);
219: if (value == null) {
220: return "";
221: }
222: return value;
223: }
224:
225: public boolean hasOption(String value) {
226: if (options == null) {
227: return false;
228: }
229: return options.containsValue(value);
230: }
231:
232: public Field getClone() {
233: return new Field(getAsElement());
234: }
235:
236: public void initOptions() {
237: if (name.type == 1) {
238: label = "Severity";
239: addOption("1", "Fatal");
240: addOption("2", "Major");
241: addOption("3", "Minor");
242: addOption("4", "Trivial");
243: addOption("5", "Suggestion");
244: } else if (name.type == 2) {
245: label = "Priority";
246: addOption("1", "Highest");
247: addOption("2", "High");
248: addOption("3", "Medium");
249: addOption("4", "Low");
250: addOption("5", "Lowest");
251: }
252: }
253:
254: //===================================================================
255:
256: public Map<String, String> getOptions() {
257: return options;
258: }
259:
260: public void setOptions(Map<String, String> options) {
261: this .options = options;
262: }
263:
264: public String getLabel() {
265: return label;
266: }
267:
268: public void setLabel(String label) {
269: this .label = label;
270: }
271:
272: public boolean isOptional() {
273: return optional;
274: }
275:
276: public void setOptional(boolean optional) {
277: this .optional = optional;
278: }
279:
280: /* custom accessor */
281: public void setName(String nameAsString) {
282: setName(convertToName(nameAsString));
283: }
284:
285: public Name getName() {
286: return name;
287: }
288:
289: public void setName(Name name) {
290: this .name = name;
291: }
292:
293: @Override
294: public String toString() {
295: StringBuffer sb = new StringBuffer();
296: sb.append("name [").append(name);
297: sb.append("]; label [").append(label);
298: sb.append("]; optional [").append(optional);
299: sb.append("]; options [").append(options);
300: sb.append("]");
301: return sb.toString();
302: }
303:
304: @Override
305: public boolean equals(Object o) {
306: if (this == o) {
307: return true;
308: }
309: if (!(o instanceof Field)) {
310: return false;
311: }
312: final Field f = (Field) o;
313: return f.getName().equals(name);
314: }
315:
316: @Override
317: public int hashCode() {
318: if (name == null) {
319: return 0;
320: }
321: return name.hashCode();
322: }
323:
324: }
|