All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.customware.confluence.plugin.google.calendar.GoogleCalendarMacro Maven / Gradle / Ivy

There is a newer version: 4.2.0
Show newest version
/*
 * 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