blob: 24d17aa6c20a86de0f050dc6ac1aa6a78c62c0f6 [file] [log] [blame]
package org.apache.maven.continuum.web.view.jsp.ui;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.views.jsp.ui.TextareaTag;
import javax.servlet.jsp.JspException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* First attempt at creating a date tag for the webwork framework. The tag will
* format a date by using either a specified format attribute, or by falling
* back on to a globally defined 'webwork.date' property.
* When nice="true" is specified, it will return a human readable string (in 2 hours, 3 minutes).
* <p/>
* From http://jira.opensymphony.com/browse/WW-805
*
* @author <a href="mailto:philip.luppens@gmail.com">Philip Luppens</a>
*/
public class DateTag
extends TextareaTag
{
/*
* the name of our property which we will use if the optional format
* parameter is not specified.
*/
public final static String DATETAG_PROPERTY = "webwork.date";
public final static String DATETAG_PROPERTY_PAST = "webwork.date.format.past";
public final static String DATETAG_DEFAULT_PAST = "{0} ago";
public final static String DATETAG_PROPERTY_FUTURE = "webwork.date.format.future";
public final static String DATETAG_DEFAULT_FUTURE = "in {0}";
public final static String DATETAG_PROPERTY_SECONDS = "webwork.date.format.seconds";
public final static String DATETAG_DEFAULT_SECONDS = "an instant";
public final static String DATETAG_PROPERTY_MINUTES = "webwork.date.format.minutes";
public final static String DATETAG_DEFAULT_MINUTES = "{0,choice,1#one minute|1<{0} minutes}";
public final static String DATETAG_PROPERTY_HOURS = "webwork.date.format.hours";
public final static String DATETAG_DEFAULT_HOURS =
"{0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one minute|1<, {1} minutes}";
public final static String DATETAG_PROPERTY_DAYS = "webwork.date.format.days";
public final static String DATETAG_DEFAULT_DAYS =
"{0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, {1} hours}";
public final static String DATETAG_PROPERTY_YEARS = "webwork.date.format.years";
public final static String DATETAG_DEFAULT_YEARS =
"{0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one day|1<, {1} days}";
//our optional format parameter
private String format;
private String actualName;
private String nameAttr;
private boolean nice;
private Date date;
private TextProvider tp;
public int doEndTag()
throws JspException
{
actualName = findString( nameAttr );
String msg = null;
ValueStack stack = getStack();
//find the name on the valueStack, and cast it to a date
Object dateObj = stack.findValue( actualName );
if ( dateObj != null )
{
if ( dateObj instanceof Date )
{
date = (Date) dateObj;
}
else if ( dateObj instanceof Long )
{
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis( ( (Long) dateObj ).longValue() );
date = cal.getTime();
}
else
{
throw new JspException( "Could not cast the requested object " + nameAttr + " to a java.util.Date" );
}
}
if ( date != null && date.getTime() > 0 )
{
tp = findProviderInStack();
if ( tp == null )
{
throw new JspException( "Could not find a TextProvider on the stack." );
}
if ( nice )
{
msg = formatTime( date );
}
else
{
if ( format == null )
{
String globalFormat = null;
//if the format is not specified, fall back using the defined
// property DATETAG_PROPERTY
globalFormat = tp.getText( DATETAG_PROPERTY );
if ( globalFormat != null )
{
msg =
new SimpleDateFormat( globalFormat, ActionContext.getContext().getLocale() ).format( date );
}
else
{
//fall back using the xwork date format ?
}
}
else
{
msg = new SimpleDateFormat( format, ActionContext.getContext().getLocale() ).format( date );
}
}
}
if ( msg != null )
{
try
{
//if we used the id attribute, we will store the formatted date
// in the valuestack, otherwise, we write it to the
// outputstream.
if ( getId() == null )
{
pageContext.getOut().write( msg );
}
else
{
stack.getContext().put( getId(), msg );
}
}
catch ( IOException e )
{
throw new JspException( e );
}
}
return EVAL_PAGE;
}
private TextProvider findProviderInStack()
{
for ( Iterator iterator = getStack().getRoot().iterator(); iterator.hasNext(); )
{
Object o = iterator.next();
if ( o instanceof TextProvider )
{
return (TextProvider) o;
}
}
return null;
}
public String formatTime( Date date )
{
StringBuffer sb = new StringBuffer();
List args = new ArrayList();
long secs = ( new Date().getTime() - date.getTime() ) / 1000;
long mins = secs / 60;
int min = (int) mins % 60;
long hours = mins / 60;
int hour = (int) hours % 24;
int days = (int) hours / 24;
int day = days % 365;
int years = days / 365;
if ( Math.abs( secs ) < 60 )
{
args.add( new Long( secs ) );
args.add( sb );
args.add( null );
sb.append( tp.getText( DATETAG_PROPERTY_SECONDS, DATETAG_DEFAULT_SECONDS, args ) );
}
else if ( hours == 0 )
{
args.add( new Long( min ) );
args.add( sb );
args.add( null );
sb.append( tp.getText( DATETAG_PROPERTY_MINUTES, DATETAG_DEFAULT_MINUTES, args ) );
}
else if ( days == 0 )
{
args.add( new Long( hour ) );
args.add( new Long( min ) );
args.add( sb );
args.add( null );
sb.append( tp.getText( DATETAG_PROPERTY_HOURS, DATETAG_DEFAULT_HOURS, args ) );
}
else if ( years == 0 )
{
args.add( new Long( days ) );
args.add( new Long( hour ) );
args.add( sb );
args.add( null );
sb.append( tp.getText( DATETAG_PROPERTY_DAYS, DATETAG_DEFAULT_DAYS, args ) );
}
else
{
args.add( new Object[]{new Long( years )} );
args.add( new Object[]{new Long( day )} );
args.add( sb );
args.add( null );
sb.append( tp.getText( DATETAG_PROPERTY_YEARS, DATETAG_DEFAULT_YEARS, args ) );
}
args.clear();
args.add( sb.toString() );
if ( date.before( new Date() ) )
{
//looks like this date is passed
return tp.getText( DATETAG_PROPERTY_PAST, DATETAG_DEFAULT_PAST, args );
}
else
{
return tp.getText( DATETAG_PROPERTY_FUTURE, DATETAG_DEFAULT_FUTURE, args );
}
}
public int doStartTag()
throws JspException
{
return super.doStartTag();
}
public void setName( String name )
{
this.nameAttr = name;
}
public String getFormat()
{
return format;
}
public void setFormat( String format )
{
this.format = format;
}
public boolean isNice()
{
return nice;
}
public void setNice( boolean nice )
{
this.nice = nice;
}
}