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