001/*
002 *   Copyright (C) Christian Schulte, 2005-206
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 4613 2012-09-22 10:07:08Z 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.logging.Level;
038import javax.xml.bind.JAXBElement;
039
040/**
041 * {@code Model} validation report.
042 *
043 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
044 * @version $JOMC: ModelValidationReport.java 4613 2012-09-22 10:07:08Z schulte $
045 */
046public class ModelValidationReport implements Serializable
047{
048
049    /** Report detail. */
050    public static class Detail implements Serializable
051    {
052
053        /** Serial version UID for backwards compatibility with 1.0.x object streams. */
054        private static final long serialVersionUID = -2466230076806042116L;
055
056        /**
057         * The detail identifier.
058         * @serial
059         */
060        private String identifier;
061
062        /**
063         * The detail level.
064         * @serial
065         */
066        private Level level;
067
068        /**
069         * The detail message.
070         * @serial
071         */
072        private String message;
073
074        /**
075         * The JAXB element this detail is associated with.
076         * @serial
077         */
078        private JAXBElement<?> element;
079
080        /**
081         * Creates a new {@code Detail} taking an identifier, a level, a message and an element.
082         *
083         * @param identifier The detail identifier.
084         * @param level The detail level.
085         * @param message The detail message.
086         * @param element The detail element.
087         */
088        public Detail( final String identifier, final Level level, final String message, final JAXBElement<?> element )
089        {
090            this.identifier = identifier;
091            this.level = level;
092            this.message = message;
093            this.element = element;
094        }
095
096        /**
097         * Gets the identifier of this detail.
098         *
099         * @return The identifier of this detail or {@code null}.
100         */
101        public String getIdentifier()
102        {
103            return this.identifier;
104        }
105
106        /**
107         * Gets the level of this detail.
108         *
109         * @return The level of this detail or {@code null}.
110         */
111        public Level getLevel()
112        {
113            return this.level;
114        }
115
116        /**
117         * Gets the message of this detail.
118         *
119         * @return The message of this detail or {@code null}.
120         */
121        public String getMessage()
122        {
123            return this.message;
124        }
125
126        /**
127         * Gets the JAXB element of this detail.
128         *
129         * @return The JAXB element of this detail or {@code null}.
130         */
131        public JAXBElement<?> getElement()
132        {
133            return this.element;
134        }
135
136        /**
137         * Creates and returns a string representation of the object.
138         *
139         * @return A string representation of the object.
140         */
141        private String toStringInternal()
142        {
143            return new StringBuilder( 200 ).append( '{' ).
144                append( "identifier=" ).append( this.getIdentifier() ).
145                append( ", level=" ).append( this.getLevel().getLocalizedName() ).
146                append( ", message=" ).append( this.getMessage() ).
147                append( ", element=" ).append( this.getElement() ).append( '}' ).toString();
148
149        }
150
151        /**
152         * Creates and returns a string representation of the object.
153         *
154         * @return A string representation of the object.
155         */
156        @Override
157        public String toString()
158        {
159            return super.toString() + this.toStringInternal();
160        }
161
162    }
163
164    /** Serial version UID for backwards compatibility with 1.0.x object streams. */
165    private static final long serialVersionUID = 6688024709865043122L;
166
167    /**
168     * Details of the instance.
169     * @serial
170     */
171    private List<Detail> details;
172
173    /** Creates a new {@code ModelValidationReport} instance. */
174    public ModelValidationReport()
175    {
176        super();
177    }
178
179    /**
180     * Gets all details of the instance.
181     * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
182     * to the returned list will be present inside the object. This is why there is no {@code set} method for the
183     * details property.</p>
184     *
185     * @return All details of the instance.
186     */
187    public List<Detail> getDetails()
188    {
189        if ( this.details == null )
190        {
191            this.details = new ArrayList<Detail>();
192        }
193
194        return this.details;
195    }
196
197    /**
198     * Gets all details of the instance matching a given identifier.
199     *
200     * @param identifier The identifier of the details to return or {@code null}.
201     *
202     * @return An unmodifiable list containing all details of the instance matching {@code identifier}.
203     */
204    public List<Detail> getDetails( final String identifier )
205    {
206        final List<Detail> list = new ArrayList<Detail>( this.getDetails().size() );
207
208        for ( int i = this.getDetails().size() - 1; i >= 0; i-- )
209        {
210            final Detail d = this.getDetails().get( i );
211            if ( identifier == null && d.getIdentifier() == null )
212            {
213                list.add( d );
214            }
215            if ( identifier != null && identifier.equals( d.getIdentifier() ) )
216            {
217                list.add( d );
218            }
219        }
220
221        return Collections.unmodifiableList( list );
222    }
223
224    /**
225     * Gets a flag indicating model validity.
226     *
227     * @return {@code true}, if all details are set to a level lower or equal to {@code WARNING}; {@code false}, if at
228     * least one detail is set to a level higher than {@code WARNING}.
229     *
230     * @see #getDetails()
231     */
232    public boolean isModelValid()
233    {
234        for ( int i = this.getDetails().size() - 1; i >= 0; i-- )
235        {
236            final Detail d = this.getDetails().get( i );
237            if ( d.getLevel() != null && d.getLevel().intValue() > Level.WARNING.intValue() )
238            {
239                return false;
240            }
241        }
242
243        return true;
244    }
245
246}