001/* Construct date token by parsing all date elements (year, day, month, ...). 002 003 @Copyright (c) 2008-2015 The Regents of the University of California. 004 All rights reserved. 005 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the 009 above copyright notice and the following two paragraphs appear in all 010 copies of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 */ 029package ptolemy.actor.lib; 030 031import java.util.Calendar; 032import java.util.TimeZone; 033 034import ptolemy.actor.TypedAtomicActor; 035import ptolemy.actor.TypedIOPort; 036import ptolemy.actor.parameters.PortParameter; 037import ptolemy.data.BooleanToken; 038import ptolemy.data.DateToken; 039import ptolemy.data.IntToken; 040import ptolemy.data.LongToken; 041import ptolemy.data.StringToken; 042import ptolemy.data.expr.Parameter; 043import ptolemy.data.expr.SingletonParameter; 044import ptolemy.data.expr.StringParameter; 045import ptolemy.data.type.BaseType; 046import ptolemy.kernel.CompositeEntity; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.NameDuplicationException; 049 050/** 051 Construct date token by parsing all date elements (year, day, month, ...). 052 053 @author Patricia Derler 054 @version $Id$ 055 @since Ptolemy II 10.0 056 @Pt.ProposedRating Red (pd) 057 @Pt.AcceptedRating Red (pd) 058 */ 059public class DateConstructor extends TypedAtomicActor { 060 061 /** Construct an actor with the given container and name. 062 * @param container The container. 063 * @param name The name of this actor. 064 * @exception IllegalActionException If the actor cannot be contained 065 * by the proposed container. 066 * @exception NameDuplicationException If the container already has an 067 * actor with this name. 068 */ 069 public DateConstructor(CompositeEntity container, String name) 070 throws NameDuplicationException, IllegalActionException { 071 super(container, name); 072 073 output = new TypedIOPort(this, "output", false, true); 074 output.setTypeEquals(BaseType.DATE); 075 076 year = new PortParameter(this, "year", new IntToken(0)); 077 new SingletonParameter(year.getPort(), "_showName") 078 .setToken(BooleanToken.TRUE); 079 080 month = new PortParameter(this, "month", new IntToken(0)); 081 month.setTypeEquals(BaseType.INT); 082 new SingletonParameter(month.getPort(), "_showName") 083 .setToken(BooleanToken.TRUE); 084 085 day = new PortParameter(this, "day", new IntToken(1)); 086 day.setTypeEquals(BaseType.INT); 087 new SingletonParameter(day.getPort(), "_showName") 088 .setToken(BooleanToken.TRUE); 089 090 hour = new PortParameter(this, "hour", new IntToken(0)); 091 hour.setTypeEquals(BaseType.INT); 092 new SingletonParameter(hour.getPort(), "_showName") 093 .setToken(BooleanToken.TRUE); 094 095 minute = new PortParameter(this, "minute", new IntToken(0)); 096 minute.setTypeEquals(BaseType.INT); 097 new SingletonParameter(minute.getPort(), "_showName") 098 .setToken(BooleanToken.TRUE); 099 100 second = new PortParameter(this, "second", new IntToken(0)); 101 second.setTypeEquals(BaseType.INT); 102 new SingletonParameter(second.getPort(), "_showName") 103 .setToken(BooleanToken.TRUE); 104 105 millisecond = new PortParameter(this, "millisecond", new IntToken(0)); 106 millisecond.setTypeEquals(BaseType.INT); 107 new SingletonParameter(millisecond.getPort(), "_showName") 108 .setToken(BooleanToken.TRUE); 109 110 microsecond = new PortParameter(this, "microsecond", new IntToken(0)); 111 microsecond.setTypeEquals(BaseType.INT); 112 new SingletonParameter(microsecond.getPort(), "_showName") 113 .setToken(BooleanToken.TRUE); 114 115 nanosecond = new PortParameter(this, "nanosecond", new IntToken(0)); 116 nanosecond.setTypeEquals(BaseType.INT); 117 new SingletonParameter(nanosecond.getPort(), "_showName") 118 .setToken(BooleanToken.TRUE); 119 120 timeZoneOffset = new PortParameter(this, "timeZoneOffset"); 121 timeZoneOffset.setTypeEquals(BaseType.INT); 122 new SingletonParameter(timeZoneOffset.getPort(), "_showName") 123 .setToken(BooleanToken.TRUE); 124 125 useTimeInMillis = new Parameter(this, "useTimeInMillis", 126 new BooleanToken(false)); 127 useTimeInMillis.setTypeEquals(BaseType.BOOLEAN); 128 129 timeInMillis = new PortParameter(this, "timeInMillis", new IntToken(0)); 130 timeInMillis.setTypeEquals(BaseType.LONG); 131 new SingletonParameter(timeInMillis.getPort(), "_showName") 132 .setToken(BooleanToken.TRUE); 133 134 precision = new StringParameter(this, "precision"); 135 precision.addChoice("second"); 136 precision.addChoice("millisecond"); 137 precision.addChoice("microsecond"); 138 precision.addChoice("nanosecond"); 139 precision.setExpression("millisecond"); 140 } 141 142 /** The output for the constructed date. 143 */ 144 public TypedIOPort output; 145 146 /** The year. 147 */ 148 public PortParameter year; 149 150 /** The month. 151 */ 152 public PortParameter month; 153 154 /** The day of the month. 155 */ 156 public PortParameter day; 157 158 /** The hour of the day. 159 */ 160 public PortParameter hour; 161 162 /** The minutes. 163 */ 164 public PortParameter minute; 165 166 /** The seconds. 167 */ 168 public PortParameter second; 169 170 /** The milliseconds. 171 */ 172 public PortParameter millisecond; 173 174 /** The microseconds. 175 */ 176 public PortParameter microsecond; 177 178 /** The nanoseconds. 179 */ 180 public PortParameter nanosecond; 181 182 /** The time zone offset. 183 */ 184 public PortParameter timeZoneOffset; 185 186 /** The time as a long value representing the milliseconds since 187 * January 1, 1970. 188 */ 189 public PortParameter timeInMillis; 190 191 /** Use the time in milliseconds. The default value is false, 192 * which means that the timeAsLongValue will be set according the 193 * year, month, day etc and adjusted according to the precision. 194 * If useTimeInMillis is true, then the value of timeAsLongValue 195 * will be the time in milliseconds. 196 */ 197 public Parameter useTimeInMillis; 198 199 /** The precision of the date. The precision defaults to 200 * milliseconds. 201 */ 202 public Parameter precision; 203 204 /////////////////////////////////////////////////////////////////// 205 //// public methods //// 206 207 /** Construct a date token with all tokens present. If a token 208 * for the long value is present, use this token and time zone 209 * as well as precision. Otherwise use tokens on other inputs to 210 * create ports. 211 * @exception IllegalActionException If thrown by the superclass, 212 * if there is no director, ifthere is a problem reading a 213 * parameter, or if there is a problem sending the date token. 214 */ 215 @Override 216 public void fire() throws IllegalActionException { 217 super.fire(); 218 DateToken dateToken = null; 219 int datePrecision = DateToken.PRECISION_MILLISECOND; 220 221 // Parse the value of the precision parameter. If the value 222 // is non-standard, default to milliseconds. 223 // FIXME:This would be better off using final strings 224 // in the constructor and here so as to avoid problems. 225 String precisionValue = ((StringToken) precision.getToken()) 226 .stringValue(); 227 if (precisionValue.equals("second")) { 228 datePrecision = DateToken.PRECISION_SECOND; 229 } else if (precisionValue.equals("millisecond")) { 230 datePrecision = DateToken.PRECISION_MILLISECOND; 231 } else if (precisionValue.equals("microsecond")) { 232 datePrecision = DateToken.PRECISION_MICROSECOND; 233 } else if (precisionValue.equals("nanosecond")) { 234 datePrecision = DateToken.PRECISION_NANOSECOND; 235 } else { 236 datePrecision = DateToken.PRECISION_MILLISECOND; 237 } 238 Integer timeZoneValue = _getIntValue(timeZoneOffset); 239 TimeZone timeZone = TimeZone.getDefault(); 240 if (timeZoneValue != null) { 241 // If offset is negative, it will already have a - sign 242 // Just need to add + sign for positive offsets 243 timeZone = TimeZone 244 .getTimeZone("GMT" + (timeZoneValue < 0 ? "" : "+") 245 + String.format("%04d", timeZoneValue)); 246 } 247 248 long timeAsLongValue = _getLongValue(timeInMillis); 249 int microsecondValue = _getIntValue(microsecond); 250 int nanosecondValue = _getIntValue(nanosecond); 251 252 if (!((BooleanToken) useTimeInMillis.getToken()).booleanValue()) { 253 int yearValue = _getIntValue(year); 254 int monthValue = _getIntValue(month); 255 int dayValue = _getIntValue(day); 256 int hourValue = _getIntValue(hour); 257 int minuteValue = _getIntValue(minute); 258 int secondValue = _getIntValue(second); 259 int millisecondValue = _getIntValue(millisecond); 260 261 Calendar c = Calendar.getInstance(timeZone); 262 c.set(Calendar.YEAR, yearValue); 263 c.set(Calendar.MONTH, monthValue); 264 c.set(Calendar.DAY_OF_MONTH, dayValue); 265 c.set(Calendar.HOUR_OF_DAY, hourValue); 266 c.set(Calendar.MINUTE, minuteValue); 267 c.set(Calendar.SECOND, secondValue); 268 c.set(Calendar.MILLISECOND, millisecondValue); 269 timeAsLongValue = c.getTimeInMillis(); 270 271 // FIXME: the precision should be an enum and this should be 272 // a switch. 273 if (datePrecision == DateToken.PRECISION_SECOND) { 274 timeAsLongValue = timeAsLongValue / 1000; 275 } else if (datePrecision == DateToken.PRECISION_MICROSECOND) { 276 timeAsLongValue = timeAsLongValue * 1000; 277 } else if (datePrecision == DateToken.PRECISION_NANOSECOND) { 278 timeAsLongValue = timeAsLongValue * 1000 * 1000; 279 } 280 } 281 dateToken = new DateToken(timeAsLongValue, datePrecision, timeZone); 282 dateToken.addMicroseconds(microsecondValue); 283 dateToken.addNanoseconds(nanosecondValue); 284 285 output.send(0, dateToken); 286 } 287 288 /////////////////////////////////////////////////////////////////// 289 //// private methods //// 290 291 private Integer _getIntValue(PortParameter portParameter) 292 throws IllegalActionException { 293 Integer value = null; 294 if (portParameter.getToken() != null) { 295 value = ((IntToken) portParameter.getToken()).intValue(); 296 } 297 if (portParameter.getPort().connectedPortList().size() > 0 298 && portParameter.getPort().hasToken(0)) { 299 value = ((IntToken) portParameter.getPort().get(0)).intValue(); 300 } 301 // // Coverity Scan reports that value could be null. 302 // if (value == null) { 303 // return Integer.valueOf(0); 304 // } 305 return value; 306 } 307 308 private Long _getLongValue(PortParameter portParameter) 309 throws IllegalActionException { 310 Long value = null; 311 if (portParameter.getToken() != null) { 312 value = ((LongToken) portParameter.getToken()).longValue(); 313 } 314 if (portParameter.getPort().connectedPortList().size() > 0 315 && portParameter.getPort().hasToken(0)) { 316 value = ((LongToken) portParameter.getPort().get(0)).longValue(); 317 } 318 // // Coverity Scan reports that value could be null. 319 // if (value == null) { 320 // return Long.valueOf(0); 321 // } 322 return value; 323 } 324 325}