001/* 002 * Copyright (c) 2015 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-10-28 21:10:03 +0000 (Wed, 28 Oct 2015) $' 007 * '$Revision: 34138 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029package org.kepler.date; 030 031import java.util.ArrayList; 032import java.util.Date; 033import java.util.List; 034 035import org.apache.commons.lang.time.DateUtils; 036 037import ptolemy.actor.TypedAtomicActor; 038import ptolemy.actor.TypedIOPort; 039import ptolemy.actor.parameters.PortParameter; 040import ptolemy.data.ArrayToken; 041import ptolemy.data.DateToken; 042import ptolemy.data.IntToken; 043import ptolemy.data.StringToken; 044import ptolemy.data.Token; 045import ptolemy.data.expr.StringParameter; 046import ptolemy.data.type.ArrayType; 047import ptolemy.data.type.BaseType; 048import ptolemy.kernel.CompositeEntity; 049import ptolemy.kernel.util.IllegalActionException; 050import ptolemy.kernel.util.NameDuplicationException; 051import ptolemy.kernel.util.SingletonAttribute; 052 053/** An actor that generates a sequence of dates between a starting and stopping 054 * date. 055 * 056 * @author Daniel Crawl 057 * @version $Id: DateSequence.java 34138 2015-10-28 21:10:03Z crawl $ 058 */ 059public class DateSequence extends TypedAtomicActor { 060 061 public DateSequence(CompositeEntity container, String name) 062 throws IllegalActionException, NameDuplicationException { 063 064 super(container, name); 065 066 start = new TypedIOPort(this, "start", true, false); 067 start.setTypeEquals(BaseType.DATE); 068 new SingletonAttribute(start, "_showName"); 069 070 stop = new TypedIOPort(this, "stop", true, false); 071 stop.setTypeEquals(BaseType.DATE); 072 new SingletonAttribute(stop, "_showName"); 073 074 step = new PortParameter(this, "step"); 075 step.setTypeEquals(BaseType.INT); 076 new SingletonAttribute(step.getPort(), "_showName"); 077 078 stepUnits = new StringParameter(this, "stepUnits"); 079 for(Units unit : Units.values()) { 080 stepUnits.addChoice(unit.toString()); 081 } 082 083 output = new TypedIOPort(this, "output", false, true); 084 output.setTypeEquals(new ArrayType(BaseType.DATE)); 085 } 086 087 @Override 088 public void fire() throws IllegalActionException { 089 090 super.fire(); 091 092 step.update(); 093 094 Token token = start.get(0); 095 if(token == null) { 096 throw new IllegalActionException(this, "Missing value for start."); 097 } 098 Date startDate = new Date(((DateToken)token).getValue()); 099 100 token = stop.get(0); 101 if(token == null) { 102 throw new IllegalActionException(this, "Missing value for stop."); 103 } 104 Date endDate = new Date(((DateToken)token).getValue()); 105 106 token = step.getToken(); 107 if(token == null) { 108 throw new IllegalActionException(this, "Missing value for step."); 109 } 110 int stepVal = ((IntToken)token).intValue(); 111 112 token = stepUnits.getToken(); 113 if(token == null) { 114 throw new IllegalActionException(this, "Missing value for stepUnits."); 115 } 116 String unitsStr = ((StringToken)token).stringValue(); 117 118 // sanity checks 119 if(startDate.after(endDate)) { 120 throw new IllegalActionException(this, "End date (" + 121 endDate + 122 ") must be equal to or after start date (" + 123 startDate + 124 ")."); 125 } 126 127 if(stepVal < 1) { 128 throw new IllegalActionException(this, "Step size must be at least 1."); 129 } 130 131 Units units = Units.valueOf(unitsStr); 132 if(units == null) { 133 throw new IllegalActionException(this, "Unknown typed of step units: " + unitsStr); 134 } 135 136 // create sequence of dates 137 List<Token> tokens = new ArrayList<Token>(); 138 Date curDate = startDate; 139 140 while(curDate.before(endDate) || curDate.equals(endDate)) { 141 142 tokens.add(new DateToken(curDate.getTime())); 143 144 // increment the current date 145 switch(units) { 146 case Second: 147 curDate = DateUtils.addSeconds(curDate, stepVal); 148 break; 149 case Minute: 150 curDate = DateUtils.addMinutes(curDate, stepVal); 151 break; 152 case Hour: 153 curDate = DateUtils.addHours(curDate, stepVal); 154 break; 155 case Day: 156 curDate = DateUtils.addDays(curDate, stepVal); 157 break; 158 case Month: 159 curDate = DateUtils.addMonths(curDate, stepVal); 160 break; 161 case Year: 162 curDate = DateUtils.addYears(curDate, stepVal); 163 break; 164 } 165 } 166 167 output.broadcast(new ArrayToken(tokens.toArray(new Token[tokens.size()]))); 168 169 } 170 171 /** The starting date. */ 172 public TypedIOPort start; 173 174 /** The stopping date. */ 175 public TypedIOPort stop; 176 177 /** The increment between steps. */ 178 public PortParameter step; 179 180 /** The units of the incremental step. */ 181 public StringParameter stepUnits; 182 183 /** The sequence of dates. */ 184 public TypedIOPort output; 185 186 /** Enumeration of unit types. */ 187 private enum Units { Year, Month, Day, Hour, Minute, Second }; 188 189}