001    package biweekly.component.marshaller;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.Comparator;
006    import java.util.Date;
007    import java.util.List;
008    
009    import biweekly.component.VFreeBusy;
010    import biweekly.property.FreeBusy;
011    import biweekly.property.ICalProperty;
012    import biweekly.util.Period;
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     * @author Michael Angstadt
041     */
042    public class VFreeBusyMarshaller extends ICalComponentMarshaller<VFreeBusy> {
043            public VFreeBusyMarshaller() {
044                    super(VFreeBusy.class, "VFREEBUSY");
045            }
046    
047            @Override
048            public List<ICalProperty> getProperties(VFreeBusy component) {
049                    List<ICalProperty> properties = super.getProperties(component);
050    
051                    List<FreeBusy> fb = new ArrayList<FreeBusy>(component.getFreeBusy());
052                    if (fb.isEmpty()) {
053                            return properties;
054                    }
055    
056                    //sort FREEBUSY properties by start date (p.100)
057                    Collections.sort(fb, new Comparator<FreeBusy>() {
058                            public int compare(FreeBusy one, FreeBusy two) {
059                                    Date oneStart = getEarliestStartDate(one);
060                                    Date twoStart = getEarliestStartDate(two);
061                                    if (oneStart == null && twoStart == null) {
062                                            return 0;
063                                    }
064                                    if (oneStart == null) {
065                                            return 1;
066                                    }
067                                    if (twoStart == null) {
068                                            return -1;
069                                    }
070                                    return oneStart.compareTo(twoStart);
071                            }
072    
073                            private Date getEarliestStartDate(FreeBusy fb) {
074                                    Date date = null;
075                                    for (Period tp : fb.getValues()) {
076                                            if (tp.getStartDate() == null) {
077                                                    continue;
078                                            }
079                                            if (date == null || date.compareTo(tp.getStartDate()) > 0) {
080                                                    date = tp.getStartDate();
081                                            }
082                                    }
083                                    return date;
084                            }
085                    });
086    
087                    //find index of first FREEBUSY instance
088                    int index = 0;
089                    for (ICalProperty prop : properties) {
090                            if (prop instanceof FreeBusy) {
091                                    break;
092                            }
093                            index++;
094                    }
095    
096                    //remove and re-add the FREEBUSY instances in sorted order
097                    for (FreeBusy f : fb) {
098                            properties.remove(f);
099                            properties.add(index++, f);
100                    }
101    
102                    return properties;
103            }
104    
105            @Override
106            protected VFreeBusy _newInstance() {
107                    return new VFreeBusy();
108            }
109    }