001 package ezvcard.io.scribe; 002 003 import java.util.HashMap; 004 import java.util.Map; 005 006 import javax.xml.namespace.QName; 007 008 import ezvcard.VCardVersion; 009 import ezvcard.property.RawProperty; 010 import ezvcard.property.VCardProperty; 011 import ezvcard.property.Xml; 012 013 /* 014 Copyright (c) 2013, Michael Angstadt 015 All rights reserved. 016 017 Redistribution and use in source and binary forms, with or without 018 modification, are permitted provided that the following conditions are met: 019 020 1. Redistributions of source code must retain the above copyright notice, this 021 list of conditions and the following disclaimer. 022 2. Redistributions in binary form must reproduce the above copyright notice, 023 this list of conditions and the following disclaimer in the documentation 024 and/or other materials provided with the distribution. 025 026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 027 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 028 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 029 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 030 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 031 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 032 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 033 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 034 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 035 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 036 */ 037 038 /** 039 * <p> 040 * Manages a listing of property scribes (marshallers). This is useful for 041 * injecting the scribes of any extended properties you have defined into a 042 * reader or writer object. The same object instance can be reused and injected 043 * into multiple reader/writer classes. 044 * </p> 045 * <p> 046 * <b>Example:</b> 047 * 048 * <pre class="brush:java"> 049 * //init the index 050 * ScribeIndex index = new ScribeIndex(); 051 * index.register(new CustomPropertyScribe()); 052 * index.register(new AnotherCustomPropertyScribe()); 053 * 054 * //inject into a reader class 055 * VCardReader vcardReader = new VCardReader(...); 056 * vcardReader.setScribeIndex(index); 057 * List<VCard> vcards = new ArrayList<VCard>(); 058 * VCard vcards; 059 * while ((vcards = vcardReader.readNext()) != null){ 060 * vcards.add(vcard); 061 * } 062 * 063 * //inject the same instance in another reader/writer class 064 * JCardWriter jcardWriter = new JCardWriter(...); 065 * jcardWriter.setScribeIndex(index); 066 * for (VCard vcard : vcards){ 067 * jcardWriter.write(vcard); 068 * } 069 * jcardWriter.close(); 070 * </pre> 071 * 072 * </p> 073 * @author Michael Angstadt 074 */ 075 public class ScribeIndex { 076 //define standard property marshallers 077 private static final Map<String, VCardPropertyScribe<? extends VCardProperty>> standardByName = new HashMap<String, VCardPropertyScribe<? extends VCardProperty>>(); 078 private static final Map<Class<? extends VCardProperty>, VCardPropertyScribe<? extends VCardProperty>> standardByClass = new HashMap<Class<? extends VCardProperty>, VCardPropertyScribe<? extends VCardProperty>>(); 079 private static final Map<QName, VCardPropertyScribe<? extends VCardProperty>> standardByQName = new HashMap<QName, VCardPropertyScribe<? extends VCardProperty>>(); 080 static { 081 //2.1, RFC 2426, RFC 6350 082 registerStandard(new AddressScribe()); 083 registerStandard(new AgentScribe()); 084 registerStandard(new AnniversaryScribe()); 085 registerStandard(new BirthdayScribe()); 086 registerStandard(new CalendarRequestUriScribe()); 087 registerStandard(new CalendarUriScribe()); 088 registerStandard(new CategoriesScribe()); 089 registerStandard(new ClassificationScribe()); 090 registerStandard(new ClientPidMapScribe()); 091 registerStandard(new EmailScribe()); 092 registerStandard(new FreeBusyUrlScribe()); 093 registerStandard(new FormattedNameScribe()); 094 registerStandard(new GenderScribe()); 095 registerStandard(new GeoScribe()); 096 registerStandard(new ImppScribe()); 097 registerStandard(new KeyScribe()); 098 registerStandard(new KindScribe()); 099 registerStandard(new LabelScribe()); 100 registerStandard(new LanguageScribe()); 101 registerStandard(new LogoScribe()); 102 registerStandard(new MailerScribe()); 103 registerStandard(new MemberScribe()); 104 registerStandard(new NicknameScribe()); 105 registerStandard(new NoteScribe()); 106 registerStandard(new OrganizationScribe()); 107 registerStandard(new PhotoScribe()); 108 registerStandard(new ProductIdScribe()); 109 registerStandard(new ProfileScribe()); 110 registerStandard(new RelatedScribe()); 111 registerStandard(new RevisionScribe()); 112 registerStandard(new RoleScribe()); 113 registerStandard(new SortStringScribe()); 114 registerStandard(new SoundScribe()); 115 registerStandard(new SourceDisplayTextScribe()); 116 registerStandard(new SourceScribe()); 117 registerStandard(new StructuredNameScribe()); 118 registerStandard(new TelephoneScribe()); 119 registerStandard(new TimezoneScribe()); 120 registerStandard(new TitleScribe()); 121 registerStandard(new UidScribe()); 122 registerStandard(new UrlScribe()); 123 124 //RFC 6351 125 registerStandard(new XmlScribe()); 126 127 //RFC 6474 128 registerStandard(new BirthplaceScribe()); 129 registerStandard(new DeathdateScribe()); 130 registerStandard(new DeathplaceScribe()); 131 132 //RFC 6715 133 registerStandard(new ExpertiseScribe()); 134 registerStandard(new OrgDirectoryScribe()); 135 registerStandard(new InterestScribe()); 136 registerStandard(new HobbyScribe()); 137 } 138 139 private final Map<String, VCardPropertyScribe<? extends VCardProperty>> extendedByName = new HashMap<String, VCardPropertyScribe<? extends VCardProperty>>(0); 140 private final Map<Class<? extends VCardProperty>, VCardPropertyScribe<? extends VCardProperty>> extendedByClass = new HashMap<Class<? extends VCardProperty>, VCardPropertyScribe<? extends VCardProperty>>(0); 141 private final Map<QName, VCardPropertyScribe<? extends VCardProperty>> extendedByQName = new HashMap<QName, VCardPropertyScribe<? extends VCardProperty>>(0); 142 143 /** 144 * Gets a property scribe by name. 145 * @param propertyName the property name (case-insensitive, e.g. "FN") 146 * @return the property scribe or null if not found 147 */ 148 public VCardPropertyScribe<? extends VCardProperty> getPropertyScribe(String propertyName) { 149 propertyName = propertyName.toUpperCase(); 150 151 VCardPropertyScribe<? extends VCardProperty> marshaller = extendedByName.get(propertyName); 152 if (marshaller != null) { 153 return marshaller; 154 } 155 156 return standardByName.get(propertyName); 157 } 158 159 /** 160 * Gets a property scribe by class. 161 * @param clazz the property class 162 * @return the property scribe or null if not found 163 */ 164 public VCardPropertyScribe<? extends VCardProperty> getPropertyScribe(Class<? extends VCardProperty> clazz) { 165 VCardPropertyScribe<? extends VCardProperty> marshaller = extendedByClass.get(clazz); 166 if (marshaller != null) { 167 return marshaller; 168 } 169 170 return standardByClass.get(clazz); 171 } 172 173 /** 174 * Gets the appropriate property scribe for a given property instance. 175 * @param property the property instance 176 * @return the property scribe or null if not found 177 */ 178 public VCardPropertyScribe<? extends VCardProperty> getPropertyScribe(VCardProperty property) { 179 if (property instanceof RawProperty) { 180 RawProperty raw = (RawProperty) property; 181 return new RawPropertyScribe(raw.getPropertyName()); 182 } 183 184 return getPropertyScribe(property.getClass()); 185 } 186 187 /** 188 * Gets a property scribe by XML local name and namespace. 189 * @param qname the XML local name and namespace 190 * @return the property scribe or a {@link XmlScribe} if not found 191 */ 192 public VCardPropertyScribe<? extends VCardProperty> getPropertyScribe(QName qname) { 193 VCardPropertyScribe<? extends VCardProperty> marshaller = extendedByQName.get(qname); 194 if (marshaller != null) { 195 return marshaller; 196 } 197 198 marshaller = standardByQName.get(qname); 199 if (marshaller != null) { 200 return marshaller; 201 } 202 203 if (VCardVersion.V4_0.getXmlNamespace().equals(qname.getNamespaceURI())) { 204 return new RawPropertyScribe(qname.getLocalPart().toUpperCase()); 205 } 206 207 return getPropertyScribe(Xml.class); 208 } 209 210 /** 211 * Registers a property scribe. 212 * @param scribe the scribe to register 213 */ 214 public void register(VCardPropertyScribe<? extends VCardProperty> scribe) { 215 extendedByName.put(scribe.getPropertyName().toUpperCase(), scribe); 216 extendedByClass.put(scribe.getPropertyClass(), scribe); 217 extendedByQName.put(scribe.getQName(), scribe); 218 } 219 220 /** 221 * Unregisters a property scribe. 222 * @param scribe the scribe to unregister 223 */ 224 public void unregister(VCardPropertyScribe<? extends VCardProperty> scribe) { 225 extendedByName.remove(scribe.getPropertyName().toUpperCase()); 226 extendedByClass.remove(scribe.getPropertyClass()); 227 extendedByQName.remove(scribe.getQName()); 228 } 229 230 private static void registerStandard(VCardPropertyScribe<? extends VCardProperty> scribe) { 231 standardByName.put(scribe.getPropertyName().toUpperCase(), scribe); 232 standardByClass.put(scribe.getPropertyClass(), scribe); 233 standardByQName.put(scribe.getQName(), scribe); 234 } 235 }