001 package org.apache.myfaces.tobago.context; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.commons.collections.iterators.EmptyIterator; 021 import org.apache.commons.collections.iterators.ObjectArrayIterator; 022 import org.apache.commons.collections.iterators.SingletonIterator; 023 import org.apache.commons.lang.ArrayUtils; 024 import org.apache.commons.lang.StringUtils; 025 026 import java.io.Serializable; 027 import java.util.ArrayList; 028 import java.util.Arrays; 029 import java.util.Iterator; 030 import java.util.List; 031 032 /** 033 * A markup signs a component to be rendered different from the normal. 034 * E. g. <code>markup="emphasized"</code> might be rendered bold 035 * or a <code>markup="deleted"</code> might be rendered with line-through style. 036 * The concrete rendering depends from the theme. 037 * <p/> 038 * The markup can also hold more than one value, e. g. <code>markup="emphasized, deleted"</code>. 039 * <p/> 040 * The value of the markup is unmodifiable. 041 * <p/> 042 * A markup must be registered for a component, before it can be used. 043 * <p/> 044 * A markup should only contain ASCII characters and digits. 045 */ 046 public final class Markup implements Serializable, Iterable<String> { 047 048 public static final Markup NULL = new Markup((String) null); 049 050 public static final Markup ASCENDING = valueOf("ascending"); 051 public static final Markup CENTER = valueOf("center"); 052 public static final Markup CLICKABLE = valueOf("clickable"); 053 public static final Markup DESCENDING = valueOf("descending"); 054 public static final Markup DELETED = valueOf("deleted"); 055 public static final Markup DISABLED = valueOf("disabled"); 056 public static final Markup ERROR = valueOf("error"); 057 public static final Markup EVEN = valueOf("even"); 058 public static final Markup FATAL = valueOf("fatal"); 059 public static final Markup FIRST = valueOf("first"); 060 public static final Markup FOLDER = valueOf("folder"); 061 public static final Markup INFO = valueOf("info"); 062 public static final Markup LEFT = valueOf("left"); 063 public static final Markup MARKED = valueOf("marked"); 064 public static final Markup MODAL = valueOf("modal"); 065 public static final Markup NUMBER = valueOf("number"); 066 public static final Markup ODD = valueOf("odd"); 067 public static final Markup PURE = valueOf("pure"); 068 public static final Markup READONLY = valueOf("readonly"); 069 public static final Markup REQUIRED = valueOf("required"); 070 public static final Markup RESIZABLE = valueOf("resizable"); 071 public static final Markup RIGHT = valueOf("right"); 072 public static final Markup SELECTED = valueOf("selected"); 073 public static final Markup SORTABLE = valueOf("sortable"); 074 public static final Markup STRONG = valueOf("strong"); 075 public static final Markup TOP = valueOf("top"); 076 public static final Markup WARN = valueOf("warn"); 077 078 /* Just one of "values" and "value" must be null */ 079 080 private final String[] values; 081 private final String value; 082 083 private Markup(String[] values) { 084 this.values = values; 085 this.value = null; 086 } 087 088 private Markup(String value) { 089 this.values = null; 090 this.value = value; 091 } 092 093 public static Markup valueOf(String[] values) { 094 if (values == null || values.length == 0) { 095 return null; 096 } else if (values.length == 1) { 097 return valueOf(values[0]); 098 } else { 099 Markup markup = new Markup((String[]) ArrayUtils.clone(values)); 100 for (int i = 0; i < markup.values.length; i++) { 101 markup.values[i] = markup.values[i].trim(); 102 } 103 return markup; 104 } 105 } 106 107 public static Markup valueOf(String value) { 108 if (StringUtils.isEmpty(value)) { 109 return null; 110 } 111 if (value.contains(",")) { 112 String[] strings = StringUtils.split(value, ", \t\n"); 113 return new Markup(strings); 114 } else { 115 return new Markup(value.trim()); 116 } 117 } 118 119 public static Markup valueOf(Object value) { 120 if (value == null) { 121 return null; 122 } 123 if (value instanceof Markup) { 124 return (Markup) value; 125 } 126 if (value instanceof String) { 127 return valueOf((String) value); 128 } 129 if (value instanceof String[]) { 130 return valueOf((String[]) value); 131 } 132 if (value instanceof Iterable) { 133 List<String> list = new ArrayList<String>(); 134 for (Object object : (Iterable) value) { 135 list.add(object.toString()); 136 } 137 return valueOf(list.toArray(new String[list.size()])); 138 } 139 return valueOf(value.toString()); 140 } 141 142 @Override 143 public boolean equals(Object o) { 144 if (this == o) { 145 return true; 146 } 147 if (o == null || getClass() != o.getClass()) { 148 return false; 149 } 150 151 Markup markup = (Markup) o; 152 153 if (value != null ? !value.equals(markup.value) : markup.value != null) { 154 return false; 155 } 156 if (!Arrays.equals(values, markup.values)) { 157 return false; 158 } 159 160 return true; 161 } 162 163 @Override 164 public int hashCode() { 165 int result = values != null ? Arrays.hashCode(values) : 0; 166 result = 31 * result + (value != null ? value.hashCode() : 0); 167 return result; 168 } 169 170 public Iterator<String> iterator() { 171 if (value != null) { 172 return new SingletonIterator(value); 173 } 174 if (values != null) { 175 return new ObjectArrayIterator(values); 176 } 177 return EmptyIterator.INSTANCE; 178 } 179 180 public Markup add(Markup markup) { 181 if (markup == null) { 182 return this; 183 } 184 if (markup == NULL) { 185 return this; 186 } 187 if (markup.value != null) { 188 return add(markup.value); 189 } else { 190 // this part is not optimized, but it will be used rarely, in the moment... 191 Markup result = this; 192 for (String summand : markup.values) { 193 result = result.add(summand); 194 } 195 return result; 196 } 197 } 198 199 private Markup add(String summand) { 200 if (summand == null) { 201 return this; 202 } 203 if (values == null) { 204 if (value == null) { 205 return valueOf(summand); 206 } else { 207 if (summand.equals(value)) { 208 return this; 209 } else { 210 return valueOf(new String[]{value, summand}); 211 } 212 } 213 } else { 214 if (ArrayUtils.contains(values, summand)) { 215 return this; 216 } else { 217 final String[] strings = new String[values.length + 1]; 218 System.arraycopy(values, 0, strings, 0, values.length); 219 strings[values.length] = summand; 220 return valueOf(strings); 221 } 222 } 223 } 224 225 public Markup remove(Markup markup) { 226 if (markup.value != null) { 227 return remove(markup.value); 228 } else { 229 // this part is not optimized, but it will be used rarely, in the moment... 230 Markup result = this; 231 for (String summand : markup.values) { 232 result = result.remove(summand); 233 } 234 return result; 235 } 236 } 237 238 private Markup remove(String summand) { 239 if (summand == null) { 240 return this; 241 } 242 if (values == null) { 243 if (value == null) { 244 return this; 245 } else { 246 if (summand.equals(value)) { 247 return NULL; 248 } else { 249 return this; 250 } 251 } 252 } else { 253 if (ArrayUtils.contains(values, summand)) { 254 final String[] strings = new String[values.length - 1]; 255 int found = 0; 256 for (int i = 0; i < strings.length; i++) { 257 if (values[i].equals(summand)) { 258 found++; 259 } 260 strings[i] = values[i + found]; 261 } 262 return valueOf(strings); 263 } else { 264 return this; 265 } 266 } 267 } 268 269 public boolean contains(String markup) { 270 if (markup == null) { 271 return false; 272 } 273 if (this == NULL) { 274 return this == Markup.valueOf(markup); 275 } 276 if (value != null) { 277 return value.equals(markup); 278 } 279 for (String value : values) { 280 if (value.equals(markup)) { 281 return true; 282 } 283 } 284 return false; 285 } 286 287 @Override 288 public String toString() { 289 if (value != null) { 290 return value; 291 } 292 if (values == null) { 293 return "null"; 294 } 295 return Arrays.toString(values); 296 } 297 }