001 package biweekly.io; 002 003 import java.util.HashMap; 004 import java.util.Map; 005 006 import javax.xml.namespace.QName; 007 008 import biweekly.ICalendar; 009 import biweekly.component.ICalComponent; 010 import biweekly.component.RawComponent; 011 import biweekly.component.marshaller.DaylightSavingsTimeMarshaller; 012 import biweekly.component.marshaller.ICalComponentMarshaller; 013 import biweekly.component.marshaller.ICalendarMarshaller; 014 import biweekly.component.marshaller.RawComponentMarshaller; 015 import biweekly.component.marshaller.StandardTimeMarshaller; 016 import biweekly.component.marshaller.VAlarmMarshaller; 017 import biweekly.component.marshaller.VEventMarshaller; 018 import biweekly.component.marshaller.VFreeBusyMarshaller; 019 import biweekly.component.marshaller.VJournalMarshaller; 020 import biweekly.component.marshaller.VTimezoneMarshaller; 021 import biweekly.component.marshaller.VTodoMarshaller; 022 import biweekly.io.xml.XCalNamespaceContext; 023 import biweekly.property.ICalProperty; 024 import biweekly.property.RawProperty; 025 import biweekly.property.Xml; 026 import biweekly.property.marshaller.ActionMarshaller; 027 import biweekly.property.marshaller.AttachmentMarshaller; 028 import biweekly.property.marshaller.AttendeeMarshaller; 029 import biweekly.property.marshaller.CalendarScaleMarshaller; 030 import biweekly.property.marshaller.CategoriesMarshaller; 031 import biweekly.property.marshaller.ClassificationMarshaller; 032 import biweekly.property.marshaller.CommentMarshaller; 033 import biweekly.property.marshaller.CompletedMarshaller; 034 import biweekly.property.marshaller.ContactMarshaller; 035 import biweekly.property.marshaller.CreatedMarshaller; 036 import biweekly.property.marshaller.DateDueMarshaller; 037 import biweekly.property.marshaller.DateEndMarshaller; 038 import biweekly.property.marshaller.DateStartMarshaller; 039 import biweekly.property.marshaller.DateTimeStampMarshaller; 040 import biweekly.property.marshaller.DescriptionMarshaller; 041 import biweekly.property.marshaller.DurationPropertyMarshaller; 042 import biweekly.property.marshaller.ExceptionDatesMarshaller; 043 import biweekly.property.marshaller.ExceptionRuleMarshaller; 044 import biweekly.property.marshaller.FreeBusyMarshaller; 045 import biweekly.property.marshaller.GeoMarshaller; 046 import biweekly.property.marshaller.ICalPropertyMarshaller; 047 import biweekly.property.marshaller.LastModifiedMarshaller; 048 import biweekly.property.marshaller.LocationMarshaller; 049 import biweekly.property.marshaller.MethodMarshaller; 050 import biweekly.property.marshaller.OrganizerMarshaller; 051 import biweekly.property.marshaller.PercentCompleteMarshaller; 052 import biweekly.property.marshaller.PriorityMarshaller; 053 import biweekly.property.marshaller.ProductIdMarshaller; 054 import biweekly.property.marshaller.RawPropertyMarshaller; 055 import biweekly.property.marshaller.RecurrenceDatesMarshaller; 056 import biweekly.property.marshaller.RecurrenceIdMarshaller; 057 import biweekly.property.marshaller.RecurrenceRuleMarshaller; 058 import biweekly.property.marshaller.RelatedToMarshaller; 059 import biweekly.property.marshaller.RepeatMarshaller; 060 import biweekly.property.marshaller.RequestStatusMarshaller; 061 import biweekly.property.marshaller.ResourcesMarshaller; 062 import biweekly.property.marshaller.SequenceMarshaller; 063 import biweekly.property.marshaller.StatusMarshaller; 064 import biweekly.property.marshaller.SummaryMarshaller; 065 import biweekly.property.marshaller.TimezoneIdMarshaller; 066 import biweekly.property.marshaller.TimezoneNameMarshaller; 067 import biweekly.property.marshaller.TimezoneOffsetFromMarshaller; 068 import biweekly.property.marshaller.TimezoneOffsetToMarshaller; 069 import biweekly.property.marshaller.TimezoneUrlMarshaller; 070 import biweekly.property.marshaller.TransparencyMarshaller; 071 import biweekly.property.marshaller.TriggerMarshaller; 072 import biweekly.property.marshaller.UidMarshaller; 073 import biweekly.property.marshaller.UrlMarshaller; 074 import biweekly.property.marshaller.VersionMarshaller; 075 import biweekly.property.marshaller.XmlMarshaller; 076 077 /* 078 Copyright (c) 2013, Michael Angstadt 079 All rights reserved. 080 081 Redistribution and use in source and binary forms, with or without 082 modification, are permitted provided that the following conditions are met: 083 084 1. Redistributions of source code must retain the above copyright notice, this 085 list of conditions and the following disclaimer. 086 2. Redistributions in binary form must reproduce the above copyright notice, 087 this list of conditions and the following disclaimer in the documentation 088 and/or other materials provided with the distribution. 089 090 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 091 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 092 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 093 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 094 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 095 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 096 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 097 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 098 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 099 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 100 */ 101 102 /** 103 * <p> 104 * Manages a listing of component and property marshallers. This is useful for 105 * injecting the marshallers of any experimental components or properties you 106 * have defined into a reader or writer object. The same object instance can be 107 * reused and injected into multiple reader/writer classes. 108 * </p> 109 * <p> 110 * <b>Example:</b> 111 * 112 * <pre class="brush:java"> 113 * //init the registrar 114 * ICalMarshallerRegistrar registrar = new ICalMarshallerRegistrar(); 115 * registrar.register(new CustomPropertyMarshaller()); 116 * registrar.register(new AnotherCustomPropertyMarshaller()); 117 * registrar.register(new CustomComponentMarshaller()); 118 * 119 * //inject into a reader class 120 * ICalReader textReader = new ICalReader(...); 121 * textReader.setRegistrar(registrar); 122 * List<ICalendar> icals = new ArrayList<ICalendar>(); 123 * ICalendar ical; 124 * while ((ical = textReader.readNext()) != null){ 125 * icals.add(ical); 126 * } 127 * 128 * //inject the same instance in another reader/writer class 129 * JCalWriter writer = new JCalWriter(...); 130 * writer.setRegistrar(registrar); 131 * for (ICalendar ical : icals){ 132 * writer.write(ical); 133 * } 134 * </pre> 135 * 136 * </p> 137 * @author Michael Angstadt 138 */ 139 public class ICalMarshallerRegistrar { 140 //define standard component marshallers 141 private static final Map<String, ICalComponentMarshaller<? extends ICalComponent>> standardCompByName = new HashMap<String, ICalComponentMarshaller<? extends ICalComponent>>(); 142 private static final Map<Class<? extends ICalComponent>, ICalComponentMarshaller<? extends ICalComponent>> standardCompByClass = new HashMap<Class<? extends ICalComponent>, ICalComponentMarshaller<? extends ICalComponent>>(); 143 static { 144 registerStandard(new ICalendarMarshaller()); 145 registerStandard(new VAlarmMarshaller()); 146 registerStandard(new VEventMarshaller()); 147 registerStandard(new VFreeBusyMarshaller()); 148 registerStandard(new VJournalMarshaller()); 149 registerStandard(new VTodoMarshaller()); 150 registerStandard(new VTimezoneMarshaller()); 151 registerStandard(new StandardTimeMarshaller()); 152 registerStandard(new DaylightSavingsTimeMarshaller()); 153 } 154 155 //define standard property marshallers 156 private static final Map<String, ICalPropertyMarshaller<? extends ICalProperty>> standardPropByName = new HashMap<String, ICalPropertyMarshaller<? extends ICalProperty>>(); 157 private static final Map<Class<? extends ICalProperty>, ICalPropertyMarshaller<? extends ICalProperty>> standardPropByClass = new HashMap<Class<? extends ICalProperty>, ICalPropertyMarshaller<? extends ICalProperty>>(); 158 private static final Map<QName, ICalPropertyMarshaller<? extends ICalProperty>> standardPropByQName = new HashMap<QName, ICalPropertyMarshaller<? extends ICalProperty>>(); 159 static { 160 //RFC 5545 161 registerStandard(new ActionMarshaller()); 162 registerStandard(new AttachmentMarshaller()); 163 registerStandard(new AttendeeMarshaller()); 164 registerStandard(new CalendarScaleMarshaller()); 165 registerStandard(new CategoriesMarshaller()); 166 registerStandard(new ClassificationMarshaller()); 167 registerStandard(new CommentMarshaller()); 168 registerStandard(new CompletedMarshaller()); 169 registerStandard(new ContactMarshaller()); 170 registerStandard(new CreatedMarshaller()); 171 registerStandard(new DateDueMarshaller()); 172 registerStandard(new DateEndMarshaller()); 173 registerStandard(new DateStartMarshaller()); 174 registerStandard(new DateTimeStampMarshaller()); 175 registerStandard(new DescriptionMarshaller()); 176 registerStandard(new DurationPropertyMarshaller()); 177 registerStandard(new ExceptionDatesMarshaller()); 178 registerStandard(new FreeBusyMarshaller()); 179 registerStandard(new GeoMarshaller()); 180 registerStandard(new LastModifiedMarshaller()); 181 registerStandard(new LocationMarshaller()); 182 registerStandard(new MethodMarshaller()); 183 registerStandard(new OrganizerMarshaller()); 184 registerStandard(new PercentCompleteMarshaller()); 185 registerStandard(new PriorityMarshaller()); 186 registerStandard(new ProductIdMarshaller()); 187 registerStandard(new RecurrenceDatesMarshaller()); 188 registerStandard(new RecurrenceIdMarshaller()); 189 registerStandard(new RecurrenceRuleMarshaller()); 190 registerStandard(new RelatedToMarshaller()); 191 registerStandard(new RepeatMarshaller()); 192 registerStandard(new RequestStatusMarshaller()); 193 registerStandard(new ResourcesMarshaller()); 194 registerStandard(new SequenceMarshaller()); 195 registerStandard(new StatusMarshaller()); 196 registerStandard(new SummaryMarshaller()); 197 registerStandard(new TimezoneIdMarshaller()); 198 registerStandard(new TimezoneNameMarshaller()); 199 registerStandard(new TimezoneOffsetFromMarshaller()); 200 registerStandard(new TimezoneOffsetToMarshaller()); 201 registerStandard(new TimezoneUrlMarshaller()); 202 registerStandard(new TransparencyMarshaller()); 203 registerStandard(new TriggerMarshaller()); 204 registerStandard(new UidMarshaller()); 205 registerStandard(new UrlMarshaller()); 206 registerStandard(new VersionMarshaller()); 207 208 //RFC 6321 209 registerStandard(new XmlMarshaller()); 210 211 //RFC 2445 212 registerStandard(new ExceptionRuleMarshaller()); 213 } 214 215 private final Map<String, ICalComponentMarshaller<? extends ICalComponent>> experimentalCompByName = new HashMap<String, ICalComponentMarshaller<? extends ICalComponent>>(0); 216 private final Map<Class<? extends ICalComponent>, ICalComponentMarshaller<? extends ICalComponent>> experimentalCompByClass = new HashMap<Class<? extends ICalComponent>, ICalComponentMarshaller<? extends ICalComponent>>(0); 217 218 private final Map<String, ICalPropertyMarshaller<? extends ICalProperty>> experimentalPropByName = new HashMap<String, ICalPropertyMarshaller<? extends ICalProperty>>(0); 219 private final Map<Class<? extends ICalProperty>, ICalPropertyMarshaller<? extends ICalProperty>> experimentalPropByClass = new HashMap<Class<? extends ICalProperty>, ICalPropertyMarshaller<? extends ICalProperty>>(0); 220 private final Map<QName, ICalPropertyMarshaller<? extends ICalProperty>> experimentalPropByQName = new HashMap<QName, ICalPropertyMarshaller<? extends ICalProperty>>(0); 221 222 /** 223 * Gets a component marshaller by name. 224 * @param componentName the component name (e.g. "VEVENT") 225 * @return the component marshaller or a {@link RawComponentMarshaller} if 226 * not found 227 */ 228 public ICalComponentMarshaller<? extends ICalComponent> getComponentMarshaller(String componentName) { 229 componentName = componentName.toUpperCase(); 230 231 ICalComponentMarshaller<? extends ICalComponent> marshaller = experimentalCompByName.get(componentName); 232 if (marshaller != null) { 233 return marshaller; 234 } 235 236 marshaller = standardCompByName.get(componentName); 237 if (marshaller != null) { 238 return marshaller; 239 } 240 241 return new RawComponentMarshaller(componentName); 242 } 243 244 /** 245 * Gets a property marshaller by name. 246 * @param propertyName the property name (e.g. "VERSION") 247 * @return the property marshaller or a {@link RawPropertyMarshaller} if not 248 * found 249 */ 250 public ICalPropertyMarshaller<? extends ICalProperty> getPropertyMarshaller(String propertyName) { 251 propertyName = propertyName.toUpperCase(); 252 253 ICalPropertyMarshaller<? extends ICalProperty> marshaller = experimentalPropByName.get(propertyName); 254 if (marshaller != null) { 255 return marshaller; 256 } 257 258 marshaller = standardPropByName.get(propertyName); 259 if (marshaller != null) { 260 return marshaller; 261 } 262 263 return new RawPropertyMarshaller(propertyName); 264 } 265 266 /** 267 * Gets a component marshaller by class. 268 * @param clazz the component class 269 * @return the component marshaller or null if not found 270 */ 271 public ICalComponentMarshaller<? extends ICalComponent> getComponentMarshaller(Class<? extends ICalComponent> clazz) { 272 ICalComponentMarshaller<? extends ICalComponent> marshaller = experimentalCompByClass.get(clazz); 273 if (marshaller != null) { 274 return marshaller; 275 } 276 277 return standardCompByClass.get(clazz); 278 } 279 280 /** 281 * Gets a property marshaller by class. 282 * @param clazz the property class 283 * @return the property marshaller or null if not found 284 */ 285 public ICalPropertyMarshaller<? extends ICalProperty> getPropertyMarshaller(Class<? extends ICalProperty> clazz) { 286 ICalPropertyMarshaller<? extends ICalProperty> marshaller = experimentalPropByClass.get(clazz); 287 if (marshaller != null) { 288 return marshaller; 289 } 290 291 return standardPropByClass.get(clazz); 292 } 293 294 /** 295 * Gets the appropriate component marshaller for a given component instance. 296 * @param component the component instance 297 * @return the component marshaller or null if not found 298 */ 299 public ICalComponentMarshaller<? extends ICalComponent> getComponentMarshaller(ICalComponent component) { 300 if (component instanceof RawComponent) { 301 RawComponent raw = (RawComponent) component; 302 return new RawComponentMarshaller(raw.getName()); 303 } 304 305 return getComponentMarshaller(component.getClass()); 306 } 307 308 /** 309 * Gets the appropriate property marshaller for a given property instance. 310 * @param property the property instance 311 * @return the property marshaller or null if not found 312 */ 313 public ICalPropertyMarshaller<? extends ICalProperty> getPropertyMarshaller(ICalProperty property) { 314 if (property instanceof RawProperty) { 315 RawProperty raw = (RawProperty) property; 316 return new RawPropertyMarshaller(raw.getName()); 317 } 318 319 return getPropertyMarshaller(property.getClass()); 320 } 321 322 /** 323 * Gets a property marshaller by XML local name and namespace. 324 * @param qname the XML local name and namespace 325 * @return the property marshaller or a {@link XmlMarshaller} if not found 326 */ 327 public ICalPropertyMarshaller<? extends ICalProperty> getPropertyMarshaller(QName qname) { 328 ICalPropertyMarshaller<? extends ICalProperty> marshaller = experimentalPropByQName.get(qname); 329 if (marshaller != null) { 330 return marshaller; 331 } 332 333 marshaller = standardPropByQName.get(qname); 334 if (marshaller != null) { 335 return marshaller; 336 } 337 338 if (XCalNamespaceContext.XCAL_NS.equals(qname.getNamespaceURI())) { 339 return new RawPropertyMarshaller(qname.getLocalPart().toUpperCase()); 340 } 341 342 return getPropertyMarshaller(Xml.class); 343 } 344 345 /** 346 * Registers a component marshaller. 347 * @param marshaller the marshaller to register 348 */ 349 public void register(ICalComponentMarshaller<? extends ICalComponent> marshaller) { 350 experimentalCompByName.put(marshaller.getComponentName().toUpperCase(), marshaller); 351 experimentalCompByClass.put(marshaller.getComponentClass(), marshaller); 352 } 353 354 /** 355 * Registers a property marshaller. 356 * @param marshaller the marshaller to register 357 */ 358 public void register(ICalPropertyMarshaller<? extends ICalProperty> marshaller) { 359 experimentalPropByName.put(marshaller.getPropertyName().toUpperCase(), marshaller); 360 experimentalPropByClass.put(marshaller.getPropertyClass(), marshaller); 361 experimentalPropByQName.put(marshaller.getQName(), marshaller); 362 } 363 364 /** 365 * Unregisters a component marshaller. 366 * @param marshaller the marshaller to unregister 367 */ 368 public void unregister(ICalComponentMarshaller<? extends ICalComponent> marshaller) { 369 experimentalCompByName.remove(marshaller.getComponentName().toUpperCase()); 370 experimentalCompByClass.remove(marshaller.getComponentClass()); 371 } 372 373 /** 374 * Unregisters a property marshaller 375 * @param marshaller the marshaller to unregister 376 */ 377 public void unregister(ICalPropertyMarshaller<? extends ICalProperty> marshaller) { 378 experimentalPropByName.remove(marshaller.getPropertyName().toUpperCase()); 379 experimentalPropByClass.remove(marshaller.getPropertyClass()); 380 experimentalPropByQName.remove(marshaller.getQName()); 381 } 382 383 /** 384 * Convenience method for getting the marshaller of the root iCalendar 385 * component ("VCALENDAR"). 386 * @return the marshaller 387 */ 388 public static ICalendarMarshaller getICalendarMarshaller() { 389 return (ICalendarMarshaller) standardCompByClass.get(ICalendar.class); 390 } 391 392 private static void registerStandard(ICalComponentMarshaller<? extends ICalComponent> marshaller) { 393 standardCompByName.put(marshaller.getComponentName().toUpperCase(), marshaller); 394 standardCompByClass.put(marshaller.getComponentClass(), marshaller); 395 } 396 397 private static void registerStandard(ICalPropertyMarshaller<? extends ICalProperty> marshaller) { 398 standardPropByName.put(marshaller.getPropertyName().toUpperCase(), marshaller); 399 standardPropByClass.put(marshaller.getPropertyClass(), marshaller); 400 standardPropByQName.put(marshaller.getQName(), marshaller); 401 } 402 }