001/* 002 * Copyright (C) 2005 Christian Schulte <cs@schulte.it> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: ModelValidationReport.java 5269 2016-08-11 23:38:09Z schulte $ 029 * 030 */ 031package org.jomc.modlet; 032 033import java.io.Serializable; 034import java.util.ArrayList; 035import java.util.Collections; 036import java.util.List; 037import java.util.concurrent.CopyOnWriteArrayList; 038import java.util.logging.Level; 039import javax.xml.bind.JAXBElement; 040 041/** 042 * {@code Model} validation report. 043 * 044 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 045 * @version $JOMC: ModelValidationReport.java 5269 2016-08-11 23:38:09Z schulte $ 046 */ 047public class ModelValidationReport implements Serializable 048{ 049 050 /** 051 * Report detail. 052 */ 053 public static class Detail implements Serializable 054 { 055 056 /** 057 * Serial version UID for backwards compatibility with 1.0.x object streams. 058 */ 059 private static final long serialVersionUID = -2466230076806042116L; 060 061 /** 062 * The detail identifier. 063 * 064 * @serial 065 */ 066 private final String identifier; 067 068 /** 069 * The detail level. 070 * 071 * @serial 072 */ 073 private final Level level; 074 075 /** 076 * The detail message. 077 * 078 * @serial 079 */ 080 private final String message; 081 082 /** 083 * The JAXB element this detail is associated with. 084 * 085 * @serial 086 */ 087 private final JAXBElement<?> element; 088 089 /** 090 * Creates a new {@code Detail} taking an identifier, a level, a message and an element. 091 * 092 * @param identifier The detail identifier. 093 * @param level The detail level. 094 * @param message The detail message. 095 * @param element The detail element. 096 */ 097 public Detail( final String identifier, final Level level, final String message, final JAXBElement<?> element ) 098 { 099 this.identifier = identifier; 100 this.level = level; 101 this.message = message; 102 this.element = element; 103 } 104 105 /** 106 * Gets the identifier of this detail. 107 * 108 * @return The identifier of this detail or {@code null}. 109 */ 110 public String getIdentifier() 111 { 112 return this.identifier; 113 } 114 115 /** 116 * Gets the level of this detail. 117 * 118 * @return The level of this detail or {@code null}. 119 */ 120 public Level getLevel() 121 { 122 return this.level; 123 } 124 125 /** 126 * Gets the message of this detail. 127 * 128 * @return The message of this detail or {@code null}. 129 */ 130 public String getMessage() 131 { 132 return this.message; 133 } 134 135 /** 136 * Gets the JAXB element of this detail. 137 * 138 * @return The JAXB element of this detail or {@code null}. 139 */ 140 public JAXBElement<?> getElement() 141 { 142 return this.element; 143 } 144 145 /** 146 * Creates and returns a string representation of the object. 147 * 148 * @return A string representation of the object. 149 */ 150 private String toStringInternal() 151 { 152 return new StringBuilder( 200 ).append( '{' ). 153 append( "identifier=" ).append( this.getIdentifier() ). 154 append( ", level=" ).append( this.getLevel().getLocalizedName() ). 155 append( ", message=" ).append( this.getMessage() ). 156 append( ", element=" ).append( this.getElement() ).append( '}' ).toString(); 157 158 } 159 160 /** 161 * Creates and returns a string representation of the object. 162 * 163 * @return A string representation of the object. 164 */ 165 @Override 166 public String toString() 167 { 168 return super.toString() + this.toStringInternal(); 169 } 170 171 } 172 173 /** 174 * Serial version UID for backwards compatibility with 1.0.x object streams. 175 */ 176 private static final long serialVersionUID = 6688024709865043122L; 177 178 /** 179 * Details of the instance. 180 * 181 * @serial 182 */ 183 private final List<Detail> details = new CopyOnWriteArrayList<Detail>(); 184 185 /** 186 * Creates a new {@code ModelValidationReport} instance. 187 */ 188 public ModelValidationReport() 189 { 190 super(); 191 } 192 193 /** 194 * Gets all details of the instance. 195 * <p> 196 * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make 197 * to the returned list will be present inside the object. This is why there is no {@code set} method for the 198 * details property. 199 * </p> 200 * 201 * @return All details of the instance. 202 */ 203 public List<Detail> getDetails() 204 { 205 return this.details; 206 } 207 208 /** 209 * Gets all details of the instance matching a given identifier. 210 * 211 * @param identifier The identifier of the details to return or {@code null}. 212 * 213 * @return An unmodifiable list containing all details of the instance matching {@code identifier}. 214 */ 215 public List<Detail> getDetails( final String identifier ) 216 { 217 final List<Detail> list = new ArrayList<Detail>( this.getDetails().size() ); 218 219 for ( final Detail detail : this.getDetails() ) 220 { 221 if ( identifier == null && detail.getIdentifier() == null ) 222 { 223 list.add( detail ); 224 } 225 if ( identifier != null && identifier.equals( detail.getIdentifier() ) ) 226 { 227 list.add( detail ); 228 } 229 } 230 231 return Collections.unmodifiableList( list ); 232 } 233 234 /** 235 * Gets a flag indicating model validity. 236 * 237 * @return {@code true}, if all details are set to a level lower or equal to {@code WARNING}; {@code false}, if at 238 * least one detail is set to a level higher than {@code WARNING}. 239 * 240 * @see #getDetails() 241 */ 242 public boolean isModelValid() 243 { 244 for ( final Detail detail : this.getDetails() ) 245 { 246 if ( detail.getLevel() != null && detail.getLevel().intValue() > Level.WARNING.intValue() ) 247 { 248 return false; 249 } 250 } 251 252 return true; 253 } 254 255}