001 /* 002 * Created on Dec 23, 2003 003 */ 004 package net.sf.jolene.dom; 005 006 import net.sf.jolene.constants.Prefs; 007 import net.sf.jolene.constants.Tags; 008 009 import java.util.*; 010 011 /** 012 * A Select in an html document. 013 * 014 * @author Dan Howard 015 */ 016 017 public final class Select extends HTMLElement { 018 019 private boolean multiple; 020 021 // Not public because we don't want the user to access the arraylist directly. 022 // The only way to add a new option is to use the addOption method. 023 List<Option> options = new ArrayList<Option>(3); 024 025 /** 026 * Default constructor. 027 */ 028 public Select() { 029 tag = Tags.select; 030 multiple = false; 031 } 032 033 034 /** 035 * Construct a select with the specified name. 036 * 037 * @param name name of the select. 038 */ 039 public Select(String name) { 040 this(); 041 setName(name); 042 } 043 044 /** 045 * This method adds a new option to the available options for the select object. 046 * 047 * @param option An option object to add to the select list 048 * @return int - the new size of the option list. 049 */ 050 public int addOption(Option option) { 051 int index = -1; 052 //option.parent = this; 053 054 StringTokenizer st = new StringTokenizer(getValue(), Prefs.SelectValueSeperator.getValue()); 055 String itemValue; 056 while (st.hasMoreTokens()) { 057 itemValue = st.nextToken(); 058 if (itemValue.equals(option.getValue())) { 059 option.setSelected(true); 060 } 061 } 062 063 options.add(option); 064 index = options.size(); 065 return index; 066 } 067 068 /** 069 * Clears the list of options on the select. 070 */ 071 public void clearOptions() { 072 options.clear(); 073 } 074 075 076 /** 077 * Returns a clone of the select object. 078 * 079 * @return Select object. 080 */ 081 @Override 082 public Select clone() { 083 Select select = (Select) super.clone(); 084 085 for (int j = 0; j < options.size(); j++) { 086 select.addOption(new Option(options.get(j).getValue(), options.get(j).getText())); 087 } 088 return select; 089 } 090 091 /** 092 * Returns the specified option object by the numeric index. 093 * 094 * @param index the index of the option to retrive 095 * @return Option object. 096 */ 097 public Option options(int index) { 098 return options.get(index); 099 } 100 101 /** 102 * Gets the value of the select object. 103 * 104 * @return value of the select object. 105 */ 106 @Override 107 public String getValue() { 108 String selectValue = super.getValue(); 109 110 // Ensure that exisiting options are flagged properly. 111 setValue(selectValue); 112 113 String value = ""; 114 115 // Loop through the options and add the values of the 'selected' options 116 // to the value string + commas... 117 String sep = Prefs.SelectValueSeperator.getValue(); 118 for (int j = 0; j < options.size(); j++) { 119 Option option = options.get(j); 120 121 if (option.isSelected()) { 122 value += option.getValue() + sep; 123 } 124 } 125 126 // Strip last comma 127 int n = value.lastIndexOf(","); 128 if (n > -1) { 129 value = value.substring(0, n); 130 } 131 132 if (value.trim().length() == 0 && selectValue.trim().length() > 0) { 133 // If there was no value found in the options list but the user 134 // had set a value in the select object itself then return that 135 // value but log a warning. 136 value = selectValue; 137 log.warn("Returning Select object " + getName() + " assigned value: " + value + " which does not exist in the options list."); 138 } 139 return value; 140 } 141 142 /** 143 * Indicates if the select is a multiple select. 144 * 145 * @return mulitple 146 */ 147 public boolean isMultiple() { 148 return multiple; 149 } 150 151 /** 152 * Set the name of the select object. 153 * 154 * @param name name of the select object. 155 */ 156 @Override 157 public void setName(String name) { 158 super.setName(name); 159 setAttribute("name", name); 160 } 161 162 /** 163 * Sets if this select is a multiple select. 164 * 165 * @param multiple boolean. 166 */ 167 public void setMultiple(boolean multiple) { 168 169 this.multiple = multiple; 170 if (multiple) { 171 setAttribute("multiple", "multiple"); 172 } else { 173 removeAttribute("multiple"); 174 } 175 } 176 177 /** 178 * Sets the value for the select object. The value to assign 179 * may be a single value or multiple values seperate by a comma. 180 * 181 * @param value String value to set. 182 */ 183 @Override 184 public void setValue(String value) { 185 super.setValue(value); 186 187 // locate the 1st option whose itemValue = value 188 // If multi-select value could be comma seperated? 189 for (int j = 0; j < options.size(); j++) { 190 191 Option option = options.get(j); 192 193 option.setSelected(false); 194 195 StringTokenizer st = new StringTokenizer(value, Prefs.SelectValueSeperator.getValue()); 196 while (st.hasMoreTokens()) { 197 String itemValue = st.nextToken(); 198 String optionValue = option.getValue(); 199 200 if (optionValue.equals(itemValue)) { 201 option.setSelected(true); 202 break; 203 } 204 } 205 } 206 207 } 208 209 /** 210 * Sort the options on the select. 211 */ 212 public void sortOptions() { 213 Collections.sort(options, new Comparator<Option>() { 214 215 public int compare(Option o1, Option o2) { 216 String s1 = o1.getText(); 217 String s2 = o2.getText(); 218 return s1.compareTo(s2); 219 } 220 }); 221 } 222 223 224 /** 225 * Renders the select. 226 * 227 * @return The select as a html string. 228 */ 229 @Override 230 public String toString() { 231 232 if (swapWith != null) { 233 return swapWith.toString(); 234 } 235 236 if (!isRenderable() && !log.isDebugEnabled()) { 237 return ""; 238 } 239 240 // Used to ensure options are initialized properly. 241 getValue(); 242 243 StringBuilder sb = new StringBuilder(super.toString()); 244 for (int j = 0; j < options.size(); j++) { 245 sb.append(options.get(j).toString()); 246 } 247 String ls = System.getProperty("line.separator"); 248 sb.append(ls); 249 sb.append("</").append(tag).append(">"); 250 sb.append(ls); 251 return sb.toString(); 252 } 253 }