001    package biweekly.property.marshaller;
002    
003    import java.util.Date;
004    import java.util.List;
005    
006    import biweekly.ICalDataType;
007    import biweekly.io.CannotParseException;
008    import biweekly.io.json.JCalValue;
009    import biweekly.io.xml.XCalElement;
010    import biweekly.parameter.ICalParameters;
011    import biweekly.property.Trigger;
012    import biweekly.util.Duration;
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     * Marshals {@link Trigger} properties.
041     * @author Michael Angstadt
042     */
043    public class TriggerMarshaller extends ICalPropertyMarshaller<Trigger> {
044            public TriggerMarshaller() {
045                    super(Trigger.class, "TRIGGER", ICalDataType.DURATION);
046            }
047    
048            @Override
049            protected ICalDataType _dataType(Trigger property) {
050                    return (property.getDate() == null) ? ICalDataType.DURATION : ICalDataType.DATE_TIME;
051            }
052    
053            @Override
054            protected String _writeText(Trigger property) {
055                    Duration duration = property.getDuration();
056                    if (duration != null) {
057                            return duration.toString();
058                    }
059    
060                    Date date = property.getDate();
061                    if (date != null) {
062                            return date(date).write();
063                    }
064    
065                    return "";
066            }
067    
068            @Override
069            protected Trigger _parseText(String value, ICalDataType dataType, ICalParameters parameters, List<String> warnings) {
070                    value = unescape(value);
071    
072                    try {
073                            Date date = date(value).tzid(parameters.getTimezoneId(), warnings).parse();
074                            return new Trigger(date);
075                    } catch (IllegalArgumentException e) {
076                            //unable to parse value as date, must be a duration
077                    }
078    
079                    try {
080                            return new Trigger(Duration.parse(value), parameters.getRelated());
081                    } catch (IllegalArgumentException e) {
082                            //unable to parse duration
083                    }
084    
085                    throw new CannotParseException("Could not parse value as a date or duration.");
086            }
087    
088            @Override
089            protected void _writeXml(Trigger property, XCalElement element) {
090                    Duration duration = property.getDuration();
091                    if (duration != null) {
092                            element.append(ICalDataType.DURATION, duration.toString());
093                            return;
094                    }
095    
096                    Date date = property.getDate();
097                    if (date != null) {
098                            element.append(ICalDataType.DATE_TIME, date(date).extended(true).write());
099                            return;
100                    }
101    
102                    element.append(defaultDataType, "");
103            }
104    
105            @Override
106            protected Trigger _parseXml(XCalElement element, ICalParameters parameters, List<String> warnings) {
107                    String value = element.first(ICalDataType.DURATION);
108                    if (value != null) {
109                            try {
110                                    return new Trigger(Duration.parse(value), parameters.getRelated());
111                            } catch (IllegalArgumentException e) {
112                                    throw new CannotParseException("Could not parse duration: " + value);
113                            }
114                    }
115    
116                    value = element.first(ICalDataType.DATE_TIME);
117                    if (value != null) {
118                            try {
119                                    Date date = date(value).tzid(parameters.getTimezoneId(), warnings).parse();
120                                    return new Trigger(date);
121                            } catch (IllegalArgumentException e) {
122                                    throw new CannotParseException("Could not parse date: " + value);
123                            }
124                    }
125    
126                    throw missingXmlElements(ICalDataType.DURATION, ICalDataType.DATE_TIME);
127            }
128    
129            @Override
130            protected JCalValue _writeJson(Trigger property) {
131                    Duration duration = property.getDuration();
132                    if (duration != null) {
133                            return JCalValue.single(duration.toString());
134                    }
135    
136                    Date date = property.getDate();
137                    if (date != null) {
138                            return JCalValue.single(date(date).extended(true).write());
139                    }
140    
141                    return JCalValue.single("");
142            }
143    
144            @Override
145            protected Trigger _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, List<String> warnings) {
146                    String valueStr = value.asSingle();
147    
148                    try {
149                            Date date = date(valueStr).tzid(parameters.getTimezoneId(), warnings).parse();
150                            return new Trigger(date);
151                    } catch (IllegalArgumentException e) {
152                            //must be a duration
153                    }
154    
155                    try {
156                            return new Trigger(Duration.parse(valueStr), parameters.getRelated());
157                    } catch (IllegalArgumentException e) {
158                            throw new CannotParseException("Could not parse value as a date or duration.");
159                    }
160            }
161    }