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 }