001package ezvcard;
002
003import java.text.NumberFormat;
004import java.util.ArrayList;
005import java.util.IdentityHashMap;
006import java.util.Iterator;
007import java.util.List;
008import java.util.Map;
009import java.util.Map.Entry;
010
011import ezvcard.property.VCardProperty;
012import ezvcard.util.ListMultimap;
013import ezvcard.util.StringUtils;
014
015/*
016 Copyright (c) 2012-2018, Michael Angstadt
017 All rights reserved.
018
019 Redistribution and use in source and binary forms, with or without
020 modification, are permitted provided that the following conditions are met: 
021
022 1. Redistributions of source code must retain the above copyright notice, this
023 list of conditions and the following disclaimer. 
024 2. Redistributions in binary form must reproduce the above copyright notice,
025 this list of conditions and the following disclaimer in the documentation
026 and/or other materials provided with the distribution. 
027
028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
029 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
030 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
032 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
034 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
037 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038 */
039
040/**
041 * <p>
042 * Holds the validation warnings of a vCard.
043 * </p>
044 * <p>
045 * <b>Examples:</b>
046 * </p>
047 * 
048 * <pre class="brush:java">
049 * //validate a vCard object according to the rules of a specific version
050 * ValidationWarnings warnings = vcard.validate(VCardVersion.V3_0);
051 * 
052 * //print all warnings to a string:
053 * System.out.println(warnings.toString());
054 * //sample output:
055 * //W01: A FormattedName property is required for vCard versions 3.0 and 4.0.
056 * //[Gender] | W02: Property is not supported in this vCard version.  Supported versions are: [4.0]
057 * 
058 * //iterate over the warnings
059 * for (Map.Entry&lt;VCardProperty, List&lt;Warning&gt;&gt; entry : warnings) {
060 *   //the property that caused the warning(s)
061 *   VCardProperty property = entry.getKey();
062 * 
063 *   //the list of warnings that belong to this property
064 *   List&lt;Warning&gt; propWarnings = entry.getValue();
065 * 
066 *   if (property == null) {
067 *     //it's a warning about the vCard as a whole
068 *   }
069 * 
070 *   //each warning message has a numeric code
071 *   //this allows you to programmatically respond to specific warning messages
072 *   List&lt;Warning&gt; propWarnings = entry.getValue();
073 *   for (Warning w : propWarnings) {
074 *     System.out.println("Code: " + w.getCode());
075 *     System.out.printkn("Message: " + w.getMessage());
076 *   }
077 * }
078 * 
079 * //you can also get the warnings of specific property classes
080 * List&lt;Warnings&gt; telWarnings = warnings.getByProperty(Telephone.class);
081 * </pre>
082 * 
083 * @author Michael Angstadt
084 * @see VCard#validate
085 */
086public class ValidationWarnings implements Iterable<Map.Entry<VCardProperty, List<ValidationWarning>>> {
087        private final ListMultimap<VCardProperty, ValidationWarning> warnings = new ListMultimap<VCardProperty, ValidationWarning>(new IdentityHashMap<VCardProperty, List<ValidationWarning>>());
088
089        /**
090         * Adds a validation warning.
091         * @param property the property that caused the warning
092         * @param warning the warning
093         */
094        public void add(VCardProperty property, ValidationWarning warning) {
095                warnings.put(property, warning);
096        }
097
098        /**
099         * Adds a property's validation warnings.
100         * @param property the property that caused the warnings
101         * @param warnings the warnings
102         */
103        public void add(VCardProperty property, List<ValidationWarning> warnings) {
104                this.warnings.putAll(property, warnings);
105        }
106
107        /**
108         * Gets all of the validation warnings.
109         * @return the validation warnings
110         */
111        public ListMultimap<VCardProperty, ValidationWarning> getWarnings() {
112                return warnings;
113        }
114
115        /**
116         * Determines whether or not the warnings list is empty.
117         * @return true if there are no warnings, false if there is at least one
118         * warning
119         */
120        public boolean isEmpty() {
121                return warnings.isEmpty();
122        }
123
124        /**
125         * Gets all validation warnings that belong to a property of a specific
126         * class.
127         * @param propertyClass the property class (e.g. {@code Telephone.class}) or
128         * null to get the warnings that apply to the vCard as a whole
129         * @return the validation warnings
130         */
131        public List<ValidationWarning> getByProperty(Class<? extends VCardProperty> propertyClass) {
132                List<ValidationWarning> propWarnings = new ArrayList<ValidationWarning>();
133                for (Map.Entry<VCardProperty, List<ValidationWarning>> entry : warnings) {
134                        VCardProperty property = entry.getKey();
135
136                        if ((property == null && propertyClass == null) || (property != null && propertyClass == property.getClass())) {
137                                List<ValidationWarning> propViolations = entry.getValue();
138                                propWarnings.addAll(propViolations);
139                        }
140                }
141                return propWarnings;
142        }
143
144        /**
145         * <p>
146         * Outputs all validation warnings as a newline-delimited string. For
147         * example:
148         * </p>
149         * 
150         * <pre>
151         * W01: A FormattedName property is required for vCard versions 3.0 and 4.0.
152         * [Gender] | W02: Property is not supported in this vCard version.  Supported versions are: [4.0]
153         * </pre>
154         */
155        @Override
156        public String toString() {
157                NumberFormat nf = NumberFormat.getIntegerInstance();
158                nf.setMinimumIntegerDigits(2);
159
160                StringBuilder sb = new StringBuilder();
161                for (Map.Entry<VCardProperty, List<ValidationWarning>> entry : warnings) {
162                        VCardProperty property = entry.getKey();
163                        List<ValidationWarning> propViolations = entry.getValue();
164
165                        for (ValidationWarning propViolation : propViolations) {
166                                if (property != null) {
167                                        sb.append('[');
168                                        sb.append(property.getClass().getSimpleName());
169                                        sb.append("] | ");
170                                }
171
172                                Integer code = propViolation.getCode();
173                                if (code != null) {
174                                        sb.append('W');
175                                        sb.append(nf.format(code));
176                                        sb.append(": ");
177                                }
178
179                                sb.append(propViolation.getMessage());
180                                sb.append(StringUtils.NEWLINE);
181                        }
182                }
183
184                return sb.toString();
185        }
186
187        public Iterator<Entry<VCardProperty, List<ValidationWarning>>> iterator() {
188                return warnings.iterator();
189        }
190}