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