com.wit.android.support.content.intent.CalendarIntent.java Source code

Java tutorial

Introduction

Here is the source code for com.wit.android.support.content.intent.CalendarIntent.java

Source

/*
 * =================================================================================================
 *                    Copyright (C) 2014 Martin Albedinsky [Wolf-ITechnologies]
 * =================================================================================================
 *         Licensed under the Apache License, Version 2.0 or later (further "License" only).
 * -------------------------------------------------------------------------------------------------
 * You may use this file only in compliance with the License. More details and copy of this License 
 * you may obtain at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * You can redistribute, modify or publish any part of the code written within this file but as it 
 * is described in the License, the software distributed under the License is distributed on an 
 * "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF ANY KIND.
 * 
 * See the License for the specific language governing permissions and limitations under the License.
 * =================================================================================================
 */
package com.wit.android.support.content.intent;

import android.app.Activity;
import android.content.ContentUris;
import android.content.Intent;
import android.net.Uri;
import android.provider.CalendarContract;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * <h3>Class Overview</h3>
 * Intent builder specialized to create CALENDAR intents.
 *
 * @author Martin Albedinsky
 */
public class CalendarIntent extends BaseIntent<CalendarIntent> {

    /**
     * Interface ===================================================================================
     */

    /**
     * <h3>Annotation Overview</h3>
     * Defines an annotation for determining set of allowed flags for {@link #type(int)} method.
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ TYPE_VIEW, TYPE_INSERT_EVENT, TYPE_EDIT_EVENT, TYPE_VIEW_EVENT })
    public @interface Type {
    }

    /**
     * <h3>Annotation Overview</h3>
     * Defines an annotation for determining set of allowed flags for {@link #availability(int)} method.
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ AVAILABILITY_BUSY, AVAILABILITY_FREE, AVAILABILITY_TENTATIVE })
    public @interface Availability {
    }

    /**
     * Constants ===================================================================================
     */

    /**
     * Log TAG.
     */
    private static final String TAG = "CalendarIntent";

    /**
     * Flag indicating whether the output trough log-cat is enabled or not.
     */
    // private static final boolean LOG_ENABLED = true;

    /**
     * Flag indicating whether the debug output trough log-cat is enabled or not.
     */
    // private static final boolean DEBUG_ENABLED = true;

    /**
     * Flag to identify CalendarIntent as intent to open calendar. Can be passed only to {@link #type(int)}.
     */
    public static final int TYPE_VIEW = 0x01;

    /**
     * Flag to identify CalendarIntent as intent to create new calendar event. Can be passed only to
     * {@link #type(int)}.
     */
    public static final int TYPE_INSERT_EVENT = 0x02;

    /**
     * Flag to identify CalendarIntent as intent to edit existing calendar event. Can be passed only
     * to {@link #type(int)}.
     */
    public static final int TYPE_EDIT_EVENT = 0x03;

    /**
     * Flag to identify CalendarIntent as intent to view existing calendar event. Can be passed only
     * to {@link #type(int)}.
     */
    public static final int TYPE_VIEW_EVENT = 0x04;

    /**
     * Flag to identify BUSY availability for the newly creating calendar event.
     * See {@link CalendarContract.Events#AVAILABILITY_BUSY} for additional info.
     */
    public static final int AVAILABILITY_BUSY = CalendarContract.Events.AVAILABILITY_BUSY;

    /**
     * Flag to identify FREE availability for the newly creating calendar event.
     * See {@link CalendarContract.Events#AVAILABILITY_FREE} for additional info.
     */
    public static final int AVAILABILITY_FREE = CalendarContract.Events.AVAILABILITY_FREE;

    /**
     * Flag to identify TENTATIVE availability for the newly creating calendar event.
     * See {@link CalendarContract.Events#AVAILABILITY_TENTATIVE} for additional info.
     */
    public static final int AVAILABILITY_TENTATIVE = 0x02;

    /**
     * Static members ==============================================================================
     */

    /**
     * Members =====================================================================================
     */

    /**
     * The type of intent creating by this builder.
     */
    private int mType = TYPE_INSERT_EVENT;

    /**
     * The id of newly creating or already existing calendar event.
     */
    private long mEventId;

    /**
     * The time for newly creating calendar event.
     */
    private long mBeginTime, mEndTime;

    /**
     * The title for newly creating calendar event.
     */
    private String mTitle;

    /**
     * The description for newly creating calendar event.
     */
    private String mDescription;

    /**
     * The locationQuery for newly creating calendar event.
     */
    private String mLocation;

    /**
     * The availability for newly creating calendar event.
     */
    private int mAvailability = AVAILABILITY_BUSY;

    /**
     * Constructors ================================================================================
     */

    /**
     * Creates a new instance of CalendarIntent for the given <var>activity</var> context with
     * the <b>begin</b> time set to the current one and <b>end</b> time set to +1 after the <b>begin</b>
     * time. See {@link com.wit.android.support.content.intent.BaseIntent#BaseIntent(android.app.Activity)}
     * for additional info.
     */
    public CalendarIntent(@NonNull Activity activity) {
        super(activity);
        this.init();
    }

    /**
     * Creates a new instance of CalendarIntent for the given <var>fragment</var> context with
     * the <b>begin</b> time set to the current one and <b>end</b> time set to +1 after the <b>begin</b>
     * time. See {@link com.wit.android.support.content.intent.BaseIntent#BaseIntent(android.support.v4.app.Fragment)}
     * for additional info.
     */
    public CalendarIntent(@NonNull Fragment fragment) {
        super(fragment);
        this.init();
    }

    /**
     * Methods =====================================================================================
     */

    /**
     * Public --------------------------------------------------------------------------------------
     */

    /**
     * Wrapped {@link System#currentTimeMillis()}.
     */
    public static long currentTime() {
        return System.currentTimeMillis();
    }

    /**
     */
    @Nullable
    @Override
    public Intent buildIntent() {
        switch (mType) {
        case TYPE_VIEW:
            if (checkTime(mBeginTime, "Time isn't valid.")) {
                final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
                builder.appendPath("time");
                ContentUris.appendId(builder, mBeginTime);
                /**
                 * Build the intent.
                 */
                return new Intent(Intent.ACTION_VIEW).setData(builder.build());
            }
            break;
        case TYPE_INSERT_EVENT:
            if (!checkTime(mBeginTime, "Begin time(" + mBeginTime + ") isn't valid.")) {
                return null;
            }
            if (!checkTime(mEndTime, "End time(" + mEndTime + ") isn't valid.")) {
                return null;
            }
            if (mEndTime <= mBeginTime) {
                this.logMessage(
                        "End time(" + mEndTime + ") is wrong specified before/at begin time(" + mBeginTime + ").");
                return null;
            }
            /**
             * Build the intent.
             */
            final Intent intent = new Intent(Intent.ACTION_INSERT).setData(CalendarContract.Events.CONTENT_URI)
                    .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, mBeginTime)
                    .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, mEndTime)
                    .putExtra(CalendarContract.Events.TITLE, mTitle)
                    .putExtra(CalendarContract.Events.DESCRIPTION, mDescription)
                    .putExtra(CalendarContract.Events.EVENT_LOCATION, mLocation)
                    .putExtra(CalendarContract.Events.AVAILABILITY, mAvailability);
            // todo: add extra emails.
            // intent.putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com");
            return intent;
        case TYPE_EDIT_EVENT:
            if (checkEventId()) {
                /**
                 * Build the intent.
                 */
                final Intent eventIntent = new Intent(Intent.ACTION_EDIT);
                eventIntent.setData(ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, mEventId));
                if (!TextUtils.isEmpty(mTitle)) {
                    eventIntent.putExtra(CalendarContract.Events.TITLE, mTitle);
                }
                return eventIntent;
            }
            break;
        case TYPE_VIEW_EVENT:
            if (checkEventId()) {
                /**
                 * Build the intent.
                 */
                return new Intent(Intent.ACTION_VIEW)
                        .setData(ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, mEventId));
            }
            break;
        }
        return null;
    }

    /**
     * Getters + Setters ---------------------------------------------------------------------------
     */

    /**
     * Returns current type of the calendar intent which will be created by this intent builder.
     *
     * @return One of: {@link #TYPE_VIEW}, {@link #TYPE_INSERT_EVENT}, {@link #TYPE_EDIT_EVENT},
     * {@link #TYPE_VIEW_EVENT}.
     */
    @Type
    public int getType() {
        return mType;
    }

    /**
     * Sets the type of calendar intent which should be created by this intent builder.
     *
     * @param type One of: {@link #TYPE_VIEW}, {@link #TYPE_INSERT_EVENT}, {@link #TYPE_EDIT_EVENT},
     * {@link #TYPE_VIEW_EVENT}.
     * @return This intent builder to allow methods chaining.
     */
    public CalendarIntent type(@Type int type) {
        switch (type) {
        case TYPE_VIEW:
        case TYPE_INSERT_EVENT:
        case TYPE_EDIT_EVENT:
        case TYPE_VIEW_EVENT:
            this.mType = type;
        }
        return this;
    }

    /**
     * Returns an id of the calendar event to edit or view within calendar. This id is used only when
     * the current type is set to: {@link #TYPE_EDIT_EVENT} or {@link #TYPE_VIEW_EVENT}.
     *
     * @return Event id.
     */
    public long getEventId() {
        return mEventId;
    }

    /**
     * Sets an id of the calendar event to edit or view, used only when the current type is set to:
     * {@link #TYPE_EDIT_EVENT} or {@link #TYPE_VIEW_EVENT}.
     *
     * @param eventId Id of the desired calendar event (to edit or view).
     * @return This intent builder to allow methods chaining.
     */
    public CalendarIntent eventId(long eventId) {
        this.mEventId = eventId;
        return this;
    }

    /**
     * Returns begin time for newly creating calendar event.
     * <p>
     * <b>Note</b>, that the default begin time is set to the current one ({@link #currentTime()}).
     *
     * @return Begin time for calendar event.
     */
    public long getBeginTime() {
        return mBeginTime;
    }

    /**
     * Sets the begin time for newly creating calendar event used only in case of type: {@link #TYPE_INSERT_EVENT}.
     * <p>
     * <b>Note</b>, that the default begin time is set to the current one ({@link #currentTime()}).
     *
     * @param beginTime The desired begin time for event in milliseconds.
     * @return This intent builder to allow methods chaining.
     * @see #endTime(long)
     */
    public CalendarIntent beginTime(long beginTime) {
        this.mBeginTime = beginTime;
        return this;
    }

    /**
     * Returns end time for newly creating calendar event.
     * <p>
     * <b>Note</b>, that the default end time is set to +1 of the current begin time ({@link #getBeginTime()}).
     *
     * @return End time for calendar event.
     */
    public long getEndTime() {
        return mEndTime;
    }

    /**
     * Sets the end time for newly creating calendar event used only in case of type: {@link #TYPE_INSERT_EVENT}.
     * <p>
     * <b>Note</b>, that the default end time is set to +1 of the current begin time ({@link #getBeginTime()}).
     *
     * @param endTime The desired end time for event in milliseconds.
     * @return This intent builder to allow methods chaining.
     */
    public CalendarIntent endTime(long endTime) {
        this.mEndTime = endTime;
        return this;
    }

    /**
     * Returns title for newly creating calendar event.
     *
     * @return Title for calendar event.
     * @see #title(int)
     * @see #title(String)
     */
    @Nullable
    public String getTitle() {
        return mTitle;
    }

    /**
     * Same as {@link #title(String)}, where string will be obtained from the current context wrapper
     * (activity/fragment).
     *
     * @param resId Resource id of the desired title text placed within an application resources.
     */
    public CalendarIntent title(@StringRes int resId) {
        return title(obtainString(resId));
    }

    /**
     * Sets the title for newly creating calendar event used only in case of type: {@link #TYPE_INSERT_EVENT}.
     *
     * @param title The desired title text.
     * @return This intent builder to allow methods chaining.
     * @see #title(int)
     */
    public CalendarIntent title(@Nullable String title) {
        mTitle = title;
        return this;
    }

    /**
     * Returns description for newly creating calendar event.
     *
     * @return Description for calendar event.
     * @see #description(int)
     * @see #description(String)
     */
    @Nullable
    public String getDescription() {
        return mDescription;
    }

    /**
     * Same as {@link #description(String)}, where string will be obtained from the current context
     * wrapper (activity/fragment).
     *
     * @param resId Resource id of the desired description text placed within an application resources.
     */
    public CalendarIntent description(@StringRes int resId) {
        return description(obtainString(resId));
    }

    /**
     * Sets the description for newly creating calendar event used only in case of type: {@link #TYPE_INSERT_EVENT}.
     *
     * @param description The desired description text.
     * @return This intent builder to allow methods chaining.
     * @see #description(int)
     */
    public CalendarIntent description(@Nullable String description) {
        mDescription = description;
        return this;
    }

    /**
     * Returns locationQuery for newly creating calendar event used only in case of type: {@link #TYPE_INSERT_EVENT}.
     *
     * @return Location for calendar event.
     */
    @Nullable
    public String getLocation() {
        return mLocation;
    }

    /**
     * Same as {@link #location(String)}, where string will be obtained from the current context wrapper
     * (activity/fragment).
     *
     * @param resId Resource id of the desired locationQuery text placed within an application resources.
     */
    public CalendarIntent location(@StringRes int resId) {
        return location(obtainString(resId));
    }

    /**
     * Sets the locationQuery for newly creating calendar event used only in case of type: {@link #TYPE_INSERT_EVENT}.
     *
     * @param location The desired locationQuery text.
     * @return This intent builder to allow methods chaining.
     * @see #location(int)
     */
    public CalendarIntent location(@Nullable String location) {
        mLocation = location;
        return this;
    }

    /**
     * Returns availability flag for newly creating calendar event.
     *
     * @return The current availability for event, one of {@link #AVAILABILITY_BUSY}, {@link #AVAILABILITY_FREE},
     * {@link #AVAILABILITY_TENTATIVE} or default {@link #AVAILABILITY_BUSY} if wasn't changed yet.
     */
    @Availability
    public int getAvailability() {
        return mAvailability;
    }

    /**
     * Sets the availability flag for newly creating calendar event used only in case of type:
     * {@link #TYPE_INSERT_EVENT}.
     * <p>
     * By default, availability is set to {@link #AVAILABILITY_BUSY}.
     *
     * @param availability One of {@link #AVAILABILITY_BUSY}, {@link #AVAILABILITY_FREE} or {@link #AVAILABILITY_TENTATIVE}.
     * @return This intent builder to allow methods chaining.
     */
    public CalendarIntent availability(@Availability int availability) {
        switch (availability) {
        case AVAILABILITY_BUSY:
        case AVAILABILITY_FREE:
        case AVAILABILITY_TENTATIVE:
            this.mAvailability = availability;
        }
        return this;
    }

    /**
     * Protected -----------------------------------------------------------------------------------
     */

    /**
     * Private -------------------------------------------------------------------------------------
     */

    /**
     * Initializes default values for this instance of calendar intent builder.
     */
    private void init() {
        this.mBeginTime = currentTime();
        this.mEndTime = mBeginTime + 1;
    }

    /**
     * Checks the current calendar event id. This will also log message in case if the current
     * event id is invalid, so use this only when the event id is required.
     *
     * @return {@code True} if the current id is valid, {@code false} otherwise.
     */
    private boolean checkEventId() {
        if (mEventId < 0) {
            this.logMessage("No event id specified.");
            return false;
        }
        return true;
    }

    /**
     * Checks the given value of time.
     *
     * @param time     Time in milliseconds to check.
     * @param errorLog Error message to log when the given time is invalid.
     * @return {@code True} if the passed time is valid ({@code 0}), {@code false}
     * otherwise.
     */
    private boolean checkTime(long time, String errorLog) {
        if (time <= 0) {
            this.logMessage(errorLog);
            return false;
        }
        return true;
    }

    /**
     * Logs the given message as error message into log cat.
     *
     * @param message Message to log.
     */
    private void logMessage(String message) {
        Log.e(TAG, "Can not crate CALENDAR intent. " + message);
    }

    /**
     * Inner classes ===============================================================================
     */
}