
net.customware.confluence.plugin.google.calendar.GoogleCalendarMacro Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-calendar-plugin Show documentation
Show all versions of google-calendar-plugin Show documentation
Creates Google Calendar links in Confluence.
/*
* Copyright (c) 2007, CustomWare Asia Pacific
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of "CustomWare Asia Pacific" nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package net.customware.confluence.plugin.google.calendar;
import static com.atlassian.confluence.util.GeneralUtil.htmlEncode;
import static com.atlassian.confluence.util.GeneralUtil.urlDecode;
import static com.atlassian.confluence.util.GeneralUtil.urlEncode;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.randombits.storage.Storage;
import org.randombits.support.confluence.ConfluenceMacro;
import org.randombits.support.confluence.MacroInfo;
import org.randombits.support.core.env.EnvironmentAssistant;
import com.atlassian.confluence.macro.MacroExecutionException;
import com.atlassian.confluence.xhtml.api.XhtmlContent;
import static com.atlassian.renderer.v2.components.HtmlEscaper.*;
/**
* TODO: Document this class.
*
* @author David Peterson
*/
/*
*
*/
public class GoogleCalendarMacro extends ConfluenceMacro {
public GoogleCalendarMacro(EnvironmentAssistant environmentAssistant, XhtmlContent xhtmlContent) {
super(environmentAssistant, xhtmlContent);
// TODO Auto-generated constructor stub
}
private static final String TIMEZONE_PARAM = "timezone";
private static final String LANGUAGE_PARAM = "language";
private static final String MODE_PARAM = "mode";
public enum Mode {
AGENDA, MONTH, WEEK
}
private static final String URLS_PARAM = "urls";
private static final String TITLE_PARAM = "title";
// private static final String EVENTS_PER_DAY_PARAM = "eventsPerDay";
private static final String FIRST_DAY_PARAM = "firstDay";
private static final String WIDTH_PARAM = "width";
private static final String HEIGHT_PARAM = "height";
private static final String CONTROLS_PARAM = "controls";
private static final String BGCOLOR_PARAM = "bgcolor";
// http://www.google.com/calendar/feeds/[email protected]/private-XXXXXXXXXXXX/basic
// http://www.google.com/calendar/ical/[email protected]/private-XXXXXXXXXXXX/basic.ics
// http://www.google.com/calendar/embed?src=rAnd0ma1pHAnuM%40group.calendar.google.com&pvttk=XXXXXXXXXXXXXX
// original regular expression
private static final Pattern CALS_PATTERN = Pattern
.compile( ".*/calendar/(?:feeds/|ical/|embed\\?src=)([^/\\&]+)(?:(?:/private-|&pvttk=)([^/]+))?.*" );
// regular expression for HTML link
private static final Pattern CALS_HTML_PATTERN = Pattern
.compile( ".*/calendar/(?:feeds/|ical/|embed\\?src=)(?:(.*)(?:&ctz=)(?:&pvttk=)?)([^/]+)?.*" );
// regular expression to validate the link type
private static final Pattern CALS_CHECKER_PATTERN = Pattern
.compile( ".*/calendar/(feeds/|ical/|embed\\?src=).*" );
public enum WeekDay {
SUNDAY(1, "su"),
MONDAY(2, "mo"),
TUESDAY(3, "tu"),
WEDNESDAY(4, "we"),
THURSDAY(5, "th"),
FRIDAY(6, "fr"),
SATURDAY(7, "sa");
public final int value;
private final String prefix;
private WeekDay( int value, String prefix ) {
this.value = value;
this.prefix = prefix;
}
public boolean matches( String name ) {
return name != null && name.toLowerCase().startsWith( prefix );
}
/**
* Finds the matching WeekDay for the provided name. If none matches,
* {@link #SUNDAY} is returned.
*
* @param name
* the name.
* @return The matching value.
*/
public static WeekDay find( String name ) {
for ( WeekDay i : values() ) {
if ( i.matches( name ) )
return i;
}
return SUNDAY;
}
}
private static final int DEFAULT_HEIGHT = 610;
private static final String DEFAULT_WIDTH = "100%";
private static final String COLORS_PARAM = "colors";
private static final String COLOR_PARAM = "color";
private static final String ENCODED_AMPERSAND = "&";
private enum Controls {
ALL( true, true, true, true, true, true, true ),
// Just navigation
NAVIGATION(false, true, true, false, false, false, false),
// None
NONE(false, false, false, false, false, false,
false);
private boolean title;
private boolean navigation;
private boolean date;
private boolean print;
private boolean tabs;
private boolean calendars;
private boolean tz;
private Controls( boolean title, boolean navigation, boolean date, boolean print, boolean tabs,
boolean calendars, boolean tz ) {
this.title = title;
this.navigation = navigation;
this.date = date;
this.print = print;
this.tabs = tabs;
this.calendars = calendars;
this.tz = tz;
}
public String getUrlParams() {
StringBuilder out = new StringBuilder();
append( "showTitle", title, out );
append( "showNav", navigation, out );
append( "showDate", date, out );
append( "showPrint", print, out );
append( "showTabs", tabs, out );
append( "showCalendars", calendars, out );
append( "showTz", tz, out );
return out.toString();
}
private void append( String name, boolean value, StringBuilder out ) {
if ( !value )
out.append( name ).append( "=0" ).append( ENCODED_AMPERSAND );
}
}
// returns the HTML iframe
@Override
public String execute( MacroInfo info ) throws MacroExecutionException {
Storage params = info.getMacroParams();
String[] colors = params.getStringArray( COLOR_PARAM, params.getStringArray( COLORS_PARAM, null ) );
String width = getWidthParam( params );
int height = getHeightParam( params );
String urls = params.getString(URLS_PARAM, "" );
if(StringUtils.isBlank(urls))
urls = info.getMacroBody();
else
urls.concat(" \n "+info.getMacroBody());
List calendars = getCalendars(urls);
StringBuffer out = new StringBuffer();
out.append( "" );
return out.toString();
}
private String getCalendarAttributes( Storage params ) throws MacroExecutionException {
StringBuffer out = new StringBuffer();
// The display mode
Mode mode = getModeParam( params );
out.append( "mode=" ).append( mode ).append( ENCODED_AMPERSAND );
// The title (optional)
String title = params.getString( TITLE_PARAM, null );
if ( title != null )
out.append( "title=" ).append( urlEncode( title ) ).append( ENCODED_AMPERSAND );
// The background colour
String bgcolor = params.getString( BGCOLOR_PARAM, null );
if ( bgcolor != null )
out.append( "bgcolor=" ).append( urlEncode( bgcolor ) ).append( ENCODED_AMPERSAND );
// The first day of the week
WeekDay firstDay = WeekDay.find( params.getString( FIRST_DAY_PARAM, null ) );
if ( firstDay != WeekDay.SUNDAY )
out.append( "wkst=" ).append( firstDay.value ).append( ENCODED_AMPERSAND );
// Controls
Controls controls = Controls.valueOf( params.getString( CONTROLS_PARAM, Controls.NAVIGATION.toString() ).toUpperCase() );
if ( controls != null )
out.append( controls.getUrlParams() );
int height = getHeightParam( params );
out.append( "height=" ).append( urlEncode( String.valueOf( height - 20 ) ) ).append( ENCODED_AMPERSAND );
// Language
String hl = params.getString( LANGUAGE_PARAM, null );
if ( hl != null )
out.append( "hl=" ).append( urlEncode( hl ) ).append( ENCODED_AMPERSAND );
// Timezone
String tz = params.getString( TIMEZONE_PARAM, null );
if ( tz != null )
out.append( "ctz=" ).append( urlEncode( tz ) ).append( ENCODED_AMPERSAND );
return out.toString();
}
private List getCalendars( String body ) throws MacroExecutionException {
String[] lines = body.trim().split( "(\r)?\n" );
List cals = new java.util.ArrayList( lines.length );
for ( int i = 0; i < lines.length; i++ ) {
// Skip comments...
if ( lines[i].startsWith( "//" ) )
continue;
// check link type
Matcher checkerMatcher = CALS_CHECKER_PATTERN.matcher( lines[i] );
String linkType = "";
if ( checkerMatcher.matches() )
linkType = checkerMatcher.group( 1 );
Matcher matcher = null;
if ( linkType.startsWith( "embed" ) )
matcher = CALS_HTML_PATTERN.matcher( lines[i] );
else
matcher = CALS_PATTERN.matcher( lines[i] );
if ( !matcher.matches() )
throw new MacroExecutionException( "Invalid Google Calendar URL: " + lines[i] );
String[] cal = new String[2];
cal[0] = matcher.group( 1 );
if ( cal[0].indexOf( '%' ) > -1 )
cal[0] = urlDecode( cal[0] );
if ( matcher.groupCount() == 2 )
cal[1] = matcher.group( 2 );
cals.add( cal );
}
return cals;
}
private String getWidthParam( Storage params ) {
return params.getString( WIDTH_PARAM, DEFAULT_WIDTH );
}
private int getHeightParam( Storage params ) throws MacroExecutionException {
try {
return params.getInteger( HEIGHT_PARAM, DEFAULT_HEIGHT );
} catch ( NumberFormatException e ) {
throw new MacroExecutionException( "Invalid height value.", e );
}
}
private Mode getModeParam( Storage params ) throws MacroExecutionException {
String modeString = params.getString( MODE_PARAM, Mode.MONTH.toString() ).toUpperCase();
Mode mode = Mode.valueOf( modeString );
if ( mode == null )
throw new MacroExecutionException( "Invalid mode specified: " + modeString );
return mode;
}
@Override
public BodyType getBodyType() {
return BodyType.PLAIN_TEXT;
}
@Override
public OutputType getOutputType() {
return OutputType.BLOCK;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy