1 /* 2 * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package de.smartics.properties.resource.util; 17 18 import java.io.Serializable; 19 import java.util.ArrayList; 20 import java.util.List; 21 22 import org.apache.commons.lang.StringUtils; 23 24 import de.smartics.exceptions.i18n.message.MessageParam; 25 import de.smartics.properties.api.core.app.AbstractBaseMessageBean; 26 import de.smartics.properties.resource.domain.ResourceCode; 27 28 /** 29 * Provides context information for errors regarding a type. 30 */ 31 public final class TypeProblemMessageBean extends AbstractBaseMessageBean 32 { 33 // ********************************* Fields ********************************* 34 35 // --- constants ------------------------------------------------------------ 36 37 /** 38 * The class version identifier. 39 * <p> 40 * The value of this constant is {@value}. 41 * </p> 42 */ 43 private static final long serialVersionUID = 1L; 44 45 // --- members -------------------------------------------------------------- 46 47 /** 48 * The type that is the cause of the problem. 49 * 50 * @serial 51 */ 52 @MessageParam("type:simpleName,fqn:name") 53 private final OgnlInterfaceFix type; 54 55 /** 56 * The list of duplicates implementations of the same type. 57 * 58 * @serial 59 */ 60 private final List<String> duplicates; 61 62 /** 63 * The list of errors encountered while trying to instantiate a service type. 64 * 65 * @serial 66 */ 67 private final List<String> errors; 68 69 // ****************************** Initializer ******************************* 70 71 // ****************************** Constructors ****************************** 72 73 /** 74 * Convenience constructor without root cause. 75 * 76 * @param type the type that is the cause of the problem. 77 */ 78 public TypeProblemMessageBean(final Class<?> type) 79 { 80 this(null, type); 81 } 82 83 /** 84 * Default constructor. 85 * 86 * @param cause the cause to the problem. 87 * @param type the type that is the cause of the problem. 88 */ 89 public TypeProblemMessageBean(final Throwable cause, final Class<?> type) 90 { 91 super(ResourceCode.FACTORY_CANNOT_INSTANTIATE_TYPE, cause); 92 this.type = new OgnlInterfaceFix(type); 93 this.duplicates = null; 94 this.errors = null; 95 } 96 97 private TypeProblemMessageBean(final Builder builder) 98 { 99 super(ResourceCode.SERVICE_FACTORY_PROBLEMS); 100 this.type = builder.type; 101 this.duplicates = builder.duplicates; 102 this.errors = builder.errors; 103 } 104 105 // ****************************** Inner Classes ***************************** 106 107 /** 108 * Wrapper around types since the OGNL library fails to get simple names from 109 * interfaces. 110 */ 111 private static final class OgnlInterfaceFix implements Serializable 112 { 113 // ******************************** Fields ******************************** 114 115 // --- constants ---------------------------------------------------------- 116 117 /** 118 * The class version identifier. 119 * <p> 120 * The value of this constant is {@value}. 121 * </p> 122 */ 123 private static final long serialVersionUID = 1L; 124 125 // --- members ------------------------------------------------------------ 126 127 /** 128 * The simple name of the wrapped interface. 129 */ 130 private final String simpleName; 131 132 /** 133 * The fqn name of the wrapped interface. 134 */ 135 private final String name; 136 137 // ***************************** Initializer ****************************** 138 139 // ***************************** Constructors ***************************** 140 141 private OgnlInterfaceFix(final Class<?> type) 142 { 143 this.simpleName = type.getSimpleName(); 144 this.name = type.getName(); 145 } 146 147 // ***************************** Inner Classes **************************** 148 149 // ******************************** Methods ******************************* 150 151 // --- init --------------------------------------------------------------- 152 153 // --- get&set ------------------------------------------------------------ 154 155 /** 156 * Returns the simple name of the wrapped interface. 157 * 158 * @return the simple name of the wrapped interface. 159 */ 160 @SuppressWarnings("unused") 161 public String getSimpleName() 162 { 163 return simpleName; 164 } 165 166 /** 167 * Returns the fqn name of the wrapped interface. 168 * 169 * @return the fqn name of the wrapped interface. 170 */ 171 @SuppressWarnings("unused") 172 public String getName() 173 { 174 return name; 175 } 176 177 // --- business ----------------------------------------------------------- 178 179 // --- object basics ------------------------------------------------------ 180 } 181 182 /** 183 * Creates instances of {@link TypeProblemMessageBean}. 184 */ 185 public static final class Builder 186 { 187 // ******************************** Fields ******************************** 188 189 // --- constants ---------------------------------------------------------- 190 191 // --- members ------------------------------------------------------------ 192 193 /** 194 * The type that is the cause of the problem. 195 */ 196 private OgnlInterfaceFix type; 197 198 /** 199 * The list of duplicates implementations of the same type. 200 */ 201 private final List<String> duplicates = new ArrayList<String>(); 202 203 /** 204 * The list of errors encountered while trying to instantiate a service 205 * type. 206 */ 207 private final List<String> errors = new ArrayList<String>(); 208 209 // ***************************** Initializer ****************************** 210 211 // ***************************** Constructors ***************************** 212 213 // ***************************** Inner Classes **************************** 214 215 // ******************************** Methods ******************************* 216 217 // --- init --------------------------------------------------------------- 218 219 // --- get&set ------------------------------------------------------------ 220 221 /** 222 * Sets the type that is the cause of the problem. 223 * 224 * @param type the type that is the cause of the problem. 225 * @return a reference to the builder. 226 */ 227 public Builder with(final Class<?> type) 228 { 229 this.type = new OgnlInterfaceFix(type); 230 return this; 231 } 232 233 /** 234 * Adds the given duplicate implementation to the list. 235 * 236 * @param duplicate the name of the implementation that implements the given 237 * type. 238 * @return a reference to the builder. 239 */ 240 public Builder withDuplicate(final String duplicate) 241 { 242 duplicates.add(duplicate); 243 return this; 244 } 245 246 /** 247 * Adds the given error message to the list. 248 * 249 * @param error the error message for detailed information on problems while 250 * instantiating a service type. 251 * @return a reference to the builder. 252 */ 253 public Builder withError(final String error) 254 { 255 errors.add(error); 256 return this; 257 } 258 259 // --- business ----------------------------------------------------------- 260 261 /** 262 * Creates the instance. 263 * 264 * @return the created instance. 265 */ 266 public TypeProblemMessageBean build() 267 { 268 return new TypeProblemMessageBean(this); 269 } 270 271 /** 272 * Creates the message. 273 * 274 * @return the created message. 275 */ 276 public String toMessage() 277 { 278 return new TypeProblemMessageBean(this).toString(); 279 } 280 281 /** 282 * Checks if duplicates or errors have been reported. 283 * 284 * @return <code>false</code> if neither duplicates or errors have been 285 * reported, <code>true</code> otherwise. 286 */ 287 public boolean hasReportedProblems() 288 { 289 return !(duplicates.isEmpty() && errors.isEmpty()); 290 } 291 292 // --- object basics ------------------------------------------------------ 293 } 294 295 // ********************************* Methods ******************************** 296 297 // --- init ----------------------------------------------------------------- 298 299 // --- get&set -------------------------------------------------------------- 300 301 // --- business ------------------------------------------------------------- 302 303 /** 304 * Returns the list of duplicates implementations of the same type. 305 * 306 * @return the list of duplicates implementations of the same type as a 307 * message. 308 */ 309 @MessageParam("duplicates") 310 public String getDuplicates() 311 { 312 return toString(duplicates); 313 } 314 315 /** 316 * Returns the count of duplicates. 317 * 318 * @return the count of duplicates. 319 */ 320 @MessageParam("duplicateCount") 321 public int getDuplicateCount() 322 { 323 return duplicates != null ? duplicates.size() : 0; 324 } 325 326 /** 327 * Returns the list of errors encountered while trying to instantiate a 328 * service type. 329 * 330 * @return the list of errors encountered while trying to instantiate a 331 * service type as a message. 332 */ 333 @MessageParam("errors") 334 public String getErrors() 335 { 336 return toString(errors); 337 } 338 339 /** 340 * Returns the count of errors. 341 * 342 * @return the count of errors. 343 */ 344 @MessageParam("errorCount") 345 public int getErrorCount() 346 { 347 return errors != null ? errors.size() : 0; 348 } 349 350 private static String toString(final List<String> items) 351 { 352 if (items == null) 353 { 354 return null; 355 } 356 357 final StringBuilder buffer = new StringBuilder(64); 358 for (final String item : items) 359 { 360 buffer.append(" ").append(item).append('\n'); 361 } 362 return StringUtils.chomp(buffer.toString()); 363 } 364 365 @Override 366 public String toString() 367 { 368 return this.getCode().getDisplayId() + ": " + this.getMessages(); 369 } 370 371 // --- object basics -------------------------------------------------------- 372 373 }