001/*
002 * Copyright (c) 2016-2017 Chris K Wensel <chris@wensel.net>. All Rights Reserved.
003 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved.
004 *
005 * Project and contact information: http://www.cascading.org/
006 *
007 * This file is part of the Cascading project.
008 *
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *     http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 */
021
022package cascading.operation.text;
023
024import java.beans.ConstructorProperties;
025import java.text.SimpleDateFormat;
026import java.util.Calendar;
027import java.util.Locale;
028import java.util.TimeZone;
029
030import cascading.flow.FlowProcess;
031import cascading.operation.BaseOperation;
032import cascading.operation.OperationCall;
033import cascading.tuple.Fields;
034import cascading.tuple.Tuple;
035import cascading.tuple.TupleEntry;
036import cascading.util.Pair;
037
038/** Class DateOperation is the base class for {@link DateFormatter} and {@link DateParser}. */
039public class DateOperation extends BaseOperation<Pair<SimpleDateFormat, TupleEntry>>
040  {
041  /** Field zone */
042  protected TimeZone zone;
043  /** Field locale */
044  protected Locale locale;
045  /** Field dateFormatString */
046  final String dateFormatString;
047
048  /**
049   * Constructor DateOperation creates a new DateOperation instance.
050   *
051   * @param numArgs          of type int
052   * @param fieldDeclaration of type Fields
053   * @param dateFormatString of type String
054   */
055  @ConstructorProperties({"numArgs", "fieldDeclaration", "dateFormatString"})
056  public DateOperation( int numArgs, Fields fieldDeclaration, String dateFormatString )
057    {
058    super( numArgs, fieldDeclaration );
059    this.dateFormatString = dateFormatString;
060
061    if( !fieldDeclaration.isSubstitution() && fieldDeclaration.size() != 1 )
062      throw new IllegalArgumentException( "fieldDeclaration may only declare one field name, got " + fieldDeclaration.print() );
063    }
064
065  /**
066   * Constructor DateOperation creates a new DateOperation instance.
067   *
068   * @param numArgs          of type int
069   * @param fieldDeclaration of type Fields
070   * @param dateFormatString of type String
071   * @param zone             of type TimeZone
072   * @param locale           of type Locale
073   */
074  @ConstructorProperties({"numArgs", "fieldDeclaration", "dateFormatString", "zone", "locale"})
075  public DateOperation( int numArgs, Fields fieldDeclaration, String dateFormatString, TimeZone zone, Locale locale )
076    {
077    super( numArgs, fieldDeclaration );
078    this.dateFormatString = dateFormatString;
079    this.zone = zone;
080    this.locale = locale;
081    }
082
083  public String getDateFormatString()
084    {
085    return dateFormatString;
086    }
087
088  /**
089   * Method getDateFormat returns the dateFormat of this DateParser object.
090   *
091   * @return the dateFormat (type SimpleDateFormat) of this DateParser object.
092   */
093  public SimpleDateFormat getDateFormat()
094    {
095    SimpleDateFormat dateFormat = new SimpleDateFormat( dateFormatString, getLocale() );
096
097    dateFormat.setTimeZone( getZone() );
098
099    return dateFormat;
100    }
101
102  private Locale getLocale()
103    {
104    if( locale != null )
105      return locale;
106
107    return Locale.getDefault();
108    }
109
110  private TimeZone getZone()
111    {
112    if( zone != null )
113      return zone;
114
115    return TimeZone.getTimeZone( "UTC" );
116    }
117
118  protected Calendar getCalendar()
119    {
120    return Calendar.getInstance( TimeZone.getTimeZone( "UTC" ), getLocale() );
121    }
122
123  @Override
124  public void prepare( FlowProcess flowProcess, OperationCall<Pair<SimpleDateFormat, TupleEntry>> operationCall )
125    {
126    operationCall.setContext( new Pair<>( getDateFormat(), new TupleEntry( operationCall.getDeclaredFields(), Tuple.size( getDeclaredSize() ) ) ) );
127    }
128
129  protected int getDeclaredSize()
130    {
131    return 1;
132    }
133
134  @Override
135  public boolean equals( Object object )
136    {
137    if( this == object )
138      return true;
139    if( !( object instanceof DateOperation ) )
140      return false;
141    if( !super.equals( object ) )
142      return false;
143
144    DateOperation that = (DateOperation) object;
145
146    if( dateFormatString != null ? !dateFormatString.equals( that.dateFormatString ) : that.dateFormatString != null )
147      return false;
148    if( locale != null ? !locale.equals( that.locale ) : that.locale != null )
149      return false;
150    if( zone != null ? !zone.equals( that.zone ) : that.zone != null )
151      return false;
152
153    return true;
154    }
155
156  @Override
157  public int hashCode()
158    {
159    int result = super.hashCode();
160    result = 31 * result + ( zone != null ? zone.hashCode() : 0 );
161    result = 31 * result + ( locale != null ? locale.hashCode() : 0 );
162    result = 31 * result + ( dateFormatString != null ? dateFormatString.hashCode() : 0 );
163    return result;
164    }
165  }