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 READONLY = valueOf("readonly"); 068 public static final Markup REQUIRED = valueOf("required"); 069 public static final Markup RESIZABLE = valueOf("resizable"); 070 public static final Markup RIGHT = valueOf("right"); 071 public static final Markup SELECTED = valueOf("selected"); 072 public static final Markup SORTABLE = valueOf("sortable"); 073 public static final Markup STRONG = valueOf("strong"); 074 public static final Markup TOP = valueOf("top"); 075 public static final Markup WARN = valueOf("warn"); 076 077 /* Just one of "values" and "value" must be null */ 078 079 private final String[] values; 080 private final String value; 081 082 private Markup(String[] values) { 083 this.values = values; 084 this.value = null; 085 } 086 087 private Markup(String value) { 088 this.values = null; 089 this.value = value; 090 } 091 092 public static Markup valueOf(String[] values) { 093 if (values == null || values.length == 0) { 094 return null; 095 } else if (values.length == 1) { 096 return valueOf(values[0]); 097 } else { 098 Markup markup = new Markup((String[]) ArrayUtils.clone(values)); 099 for (int i = 0; i < markup.values.length; i++) { 100 markup.values[i] = markup.values[i].trim(); 101 } 102 return markup; 103 } 104 } 105 106 public static Markup valueOf(String value) { 107 if (StringUtils.isEmpty(value)) { 108 return null; 109 } 110 if (value.contains(",")) { 111 String[] strings = StringUtils.split(value, ", \t\n"); 112 return new Markup(strings); 113 } else { 114 return new Markup(value.trim()); 115 } 116 } 117 118 public static Markup valueOf(Object value) { 119 if (value == null) { 120 return null; 121 } 122 if (value instanceof Markup) { 123 return (Markup) value; 124 } 125 if (value instanceof String) { 126 return valueOf((String) value); 127 } 128 if (value instanceof String[]) { 129 return valueOf((String[]) value); 130 } 131 if (value instanceof Iterable) { 132 List<String> list = new ArrayList<String>(); 133 for (Object object : (Iterable) value) { 134 list.add(object.toString()); 135 } 136 return valueOf(list.toArray(new String[list.size()])); 137 } 138 return valueOf(value.toString()); 139 } 140 141 @Override 142 public boolean equals(Object o) { 143 if (this == o) { 144 return true; 145 } 146 if (o == null || getClass() != o.getClass()) { 147 return false; 148 } 149 150 Markup markup = (Markup) o; 151 152 if (value != null ? !value.equals(markup.value) : markup.value != null) { 153 return false; 154 } 155 if (!Arrays.equals(values, markup.values)) { 156 return false; 157 } 158 159 return true; 160 } 161 162 @Override 163 public int hashCode() { 164 int result = values != null ? Arrays.hashCode(values) : 0; 165 result = 31 * result + (value != null ? value.hashCode() : 0); 166 return result; 167 } 168 169 public Iterator<String> iterator() { 170 if (value != null) { 171 return new SingletonIterator(value); 172 } 173 if (values != null) { 174 return new ObjectArrayIterator(values); 175 } 176 return EmptyIterator.INSTANCE; 177 } 178 179 public Markup add(Markup markup) { 180 if (markup == null) { 181 return this; 182 } 183 if (markup == NULL) { 184 return this; 185 } 186 if (markup.value != null) { 187 return add(markup.value); 188 } else { 189 // this part is not optimized, but it will be used rarely, in the moment... 190 Markup result = this; 191 for (String summand : markup.values) { 192 result = result.add(summand); 193 } 194 return result; 195 } 196 } 197 198 private Markup add(String summand) { 199 if (summand == null) { 200 return this; 201 } 202 if (values == null) { 203 if (value == null) { 204 return valueOf(summand); 205 } else { 206 if (summand.equals(value)) { 207 return this; 208 } else { 209 return valueOf(new String[]{value, summand}); 210 } 211 } 212 } else { 213 if (ArrayUtils.contains(values, summand)) { 214 return this; 215 } else { 216 final String[] strings = new String[values.length + 1]; 217 System.arraycopy(values, 0, strings, 0, values.length); 218 strings[values.length] = summand; 219 return valueOf(strings); 220 } 221 } 222 } 223 224 public Markup remove(Markup markup) { 225 if (markup.value != null) { 226 return remove(markup.value); 227 } else { 228 // this part is not optimized, but it will be used rarely, in the moment... 229 Markup result = this; 230 for (String summand : markup.values) { 231 result = result.remove(summand); 232 } 233 return result; 234 } 235 } 236 237 private Markup remove(String summand) { 238 if (summand == null) { 239 return this; 240 } 241 if (values == null) { 242 if (value == null) { 243 return this; 244 } else { 245 if (summand.equals(value)) { 246 return NULL; 247 } else { 248 return this; 249 } 250 } 251 } else { 252 if (ArrayUtils.contains(values, summand)) { 253 final String[] strings = new String[values.length - 1]; 254 int found = 0; 255 for (int i = 0; i < strings.length; i++) { 256 if (values[i].equals(summand)) { 257 found++; 258 } 259 strings[i] = values[i + found]; 260 } 261 return valueOf(strings); 262 } else { 263 return this; 264 } 265 } 266 } 267 268 @Override 269 public String toString() { 270 if (value != null) { 271 return value; 272 } 273 if (values == null) { 274 return "null"; 275 } 276 return Arrays.toString(values); 277 } 278 }