/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.api.engine.scheduling.domain;

import com.jaspersoft.jasperserver.api.JasperServerAPI;
import com.jaspersoft.jasperserver.api.engine.scheduling.service.ReportSchedulingService;
import com.jaspersoft.jasperserver.api.metadata.common.domain.ContentResource;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;



/**
 * Definition of a report execution job.
 * 
 * <p>
 * A report job definition specifies wich report to execute and when, 
 * what output to generate and where to send the output.
 * </p>
 * 
 * @author Lucian Chirita (lucianc@users.sourceforge.net)
 * @version $Id: ReportJob.java 19921 2010-12-11 14:52:49Z tmatyashovsky $
 * @since 1.0
 * @see ReportSchedulingService#scheduleJob(com.jaspersoft.jasperserver.api.common.domain.ExecutionContext, ReportJob)
 */
@JasperServerAPI
public class ReportJob implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * The version number which should be used for new (unsaved) report jobs.
	 * 
	 * @see #getVersion()
	 */
	public static final int VERSION_NEW = -1;
	
	/**
	 * PDF output constant.
	 * 
	 * @see #getOutputFormats()
	 */
	public static final byte OUTPUT_FORMAT_PDF = 1;
	
	/**
	 * HTML output constant.
	 * 
	 * @see #getOutputFormats()
	 */
	public static final byte OUTPUT_FORMAT_HTML = 2;
	
	/**
	 * XLS output constant.
	 * 
	 * @see #getOutputFormats()
	 */
	public static final byte OUTPUT_FORMAT_XLS = 3;
	
	/**
	 * RTF output constant.
	 * 
	 * @see #getOutputFormats()
	 */
	public static final byte OUTPUT_FORMAT_RTF = 4;
	
	/**
	 * CSV output constant.
	 * 
	 * @see #getOutputFormats()
	 * @since 2.0.0
	 */
	public static final byte OUTPUT_FORMAT_CSV = 5;
	
	/**
	 * ODT output constant.
	 * 
	 * @see #getOutputFormats()
	 * @since 3.7.0
	 */
	public static final byte OUTPUT_FORMAT_ODT = 6;
	
	/**
	 * TXT output constant.
	 * 
	 * @see #getOutputFormats()
	 * @since 3.7.0
	 */
	public static final byte OUTPUT_FORMAT_TXT = 7;
	
	/**
	 * DOCX output constant.
	 * 
	 * @see #getOutputFormats()
	 * @since 3.7.0
	 */
	public static final byte OUTPUT_FORMAT_DOCX = 8;
	
	/**
	 * ODS output constant.
	 * 
	 * @see #getOutputFormats()
	 * @since 3.7.0
	 */
	public static final byte OUTPUT_FORMAT_ODS = 9;
	
	/**
	 * XLSX output constant.
	 * 
	 * @see #getOutputFormats()
	 * @since 3.7.0
	 */
	public static final byte OUTPUT_FORMAT_XLSX = 10;

	private long id;
	private int version = VERSION_NEW;
	private String username;
	private String label;
	private String description;
	private ReportJobTrigger trigger;
	private ReportJobSource source;
	private String baseOutputFilename;
	private Set outputFormats;
	private String outputLocale;
	private ReportJobRepositoryDestination contentRepositoryDestination;
	private ReportJobMailNotification mailNotification;

	/**
	 * Creates a new empty report job.
	 */
	public ReportJob() {
		outputFormats = new HashSet();
	}

	/**
	 * Returns the job ID.
	 * 
	 * <p>
	 * Unsaved jobs will not an ID, as the ID is generated at save time.
	 * </p>
	 * 
	 * @return the job ID, or <code>0</code> for unsaved jobs
	 */
	public long getId() {
		return id;
	}

	/**
	 * Sets the job ID.
	 * 
	 * <p>
	 * A job ID needs to be set only when preparing a report job for an update
	 * operation.  The update operation will use the ID to locate the existing
	 * job and update its details.
	 * </p>
	 * 
	 * @param id the job ID
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * Returns the persistent version of this report job object.
	 * 
	 * <p>
	 * When a report job is retrieved from the scheduling service, its version
	 * is automatically set.
	 * The version needs to be preserved if the report job details are going to
	 * be updated.
	 * </p>
	 * 
	 * @return the version of this report job
	 * @see #VERSION_NEW
	 * @see #setVersion(int)
	 */
	public int getVersion() {
		return version;
	}

	/**
	 * Sets the persistent version of this report job.
	 * 
	 * <p>
	 * The version is set to <code>VERSION_NEW</code> by default when a new
	 * object is created.  It doesn't need to change when the report job is
	 * initially saved in the repository.
	 * </p>
	 * 
	 * <p>
	 * When updating a report job, the version should preserve the same value
	 * as the one contained in the object returned from the repository.
	 * When the job details are updated, the service will verify that the version
	 * in the job object passed as argument is the same as the latest version
	 * of the persisted job.
	 * If the versions do not match, the update will fail.
	 * </p>
	 * 
	 * @param version the report job persistent version
	 */
	public void setVersion(int version) {
		this.version = version;
	}

	/**
	 * Returns the report execution source, consisting of a report and a set
	 * of input values for the report.
	 * 
	 * 
	 * @return the report execution source
	 * @see #setSource(ReportJobSource)
	 */
	public ReportJobSource getSource() {
		return source;
	}

	/**
	 * Sets the report execution source for this job.
	 * 
	 * <p>
	 * A report job needs to be set a source before being saved.
	 * </p>
	 * 
	 * @param source the report job source
	 */
	public void setSource(ReportJobSource source) {
		this.source = source;
	}

	/**
	 * Returns the job trigger, which specifies when the report should be 
	 * executed.
	 * 
	 * @return the job trigger
	 * @see #setTrigger(ReportJobTrigger)
	 */
	public ReportJobTrigger getTrigger() {
		return trigger;
	}

	/**
	 * Sets the report job trigger.
	 * 
	 * <p>
	 * The trigger defines when the report jobs is to be executed.
	 * A job can be executed only once or can recur either at fixed intervals
	 * or at specific calendar moments.
	 * </p>
	 * 
	 * @param trigger the job trigger
	 * @see ReportJobSimpleTrigger
	 * @see ReportJobCalendarTrigger
	 */
	public void setTrigger(ReportJobTrigger trigger) {
		this.trigger = trigger;
	}

	/**
	 * Returns the information related to the email notification which is to be
	 * sent at job execution time.
	 * 
	 * @return email notification information associated with the job, or
	 * <code>null</code> if the job is not to send any notification
	 * @see #setMailNotification(ReportJobMailNotification)
	 */
	public ReportJobMailNotification getMailNotification() {
		return mailNotification;
	}

	/**
	 * Defines an email notification for the report job.
	 * 
	 * <p>
	 * An email notification will be send each time the report job executes.
	 * </p>
	 * 
	 * @param mailNotification the job email notification information
	 */
	public void setMailNotification(ReportJobMailNotification mailNotification) {
		this.mailNotification = mailNotification;
	}

	/**
	 * Returns information related to the repository output of the report job.
	 * 
	 * <p>
	 * The output files created by the job are saved in the repository as
	 * content resources.
	 * This method provides attributes related to way the repository resources
	 * should be generated.
	 * </p>
	 * 
	 * @return repository output information
	 * @see ContentResource
	 */
	public ReportJobRepositoryDestination getContentRepositoryDestination() {
		return contentRepositoryDestination;
	}

	/**
	 * Sets attributes that specify how the job output is to be saved in the
	 * repository.
	 * 
	 * <p>
	 * These attributes need to be set prior to scheduling the job as the 
	 * repository output is mandatory.
	 * </p>
	 * 
	 * @param contentRepositoryDestination repository output attributes
	 */
	public void setContentRepositoryDestination(
			ReportJobRepositoryDestination contentRepositoryDestination) {
		this.contentRepositoryDestination = contentRepositoryDestination;
	}

	/**
	 * Returns a long description of the report job. 
	 * 
	 * @return the job description
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * Sets a description for the job
	 * 
	 * @param description the job description
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * Returns a short description of the report job.
	 * 
	 * @return the job label
	 */
	public String getLabel() {
		return label;
	}

	/**
	 * Sets a mandatory short description for the report job.
	 * 
	 * @param label the job label
	 */
	public void setLabel(String label) {
		this.label = label;
	}

	/**
	 * Returns the base name that will be used for job output file nanes.
	 * 
	 * <p>
	 * The base output file name gets suffixed by a timestamp if the job is
	 * configured to generate sequential file names, and by an extension that
	 * depends on the output type.
	 * </p>
	 * 
	 * @return
	 * @see ReportJobRepositoryDestination#isSequentialFilenames()
	 */
	public String getBaseOutputFilename() {
		return baseOutputFilename;
	}

	/**
	 * Sets the base filename to be used for the report job output files.
	 * 
	 * @param baseOutputFilename the job output base filename
	 * @see #getBaseOutputFilename()
	 */
	public void setBaseOutputFilename(String baseOutputFilename) {
		this.baseOutputFilename = baseOutputFilename;
	}

	/**
	 * Returns the set of output formats what will be generated by the job.
	 * 
	 * <p>
	 * The output formats are returned as <code>java.lang.Byte</code> keys.
	 * A output format key can be one of the <code>OUTPUT_FORMAT_*</code>,
	 * or a different format for which support has been added as a customization.
	 * </p>
	 * 
	 * @return a set of output formats as <code>java.lang.Byte</code> keys
	 */
	public Set getOutputFormats() {
		return outputFormats;
	}

	/**
	 * Sets the list of output formats that will be generated by the job.
	 * 
	 * @param outputFormats the set of output formats as 
	 * <code>java.lang.Byte</code> keys
	 * @see #getOutputFormats()
	 */
	public void setOutputFormats(Set outputFormats) {
		this.outputFormats = outputFormats;
	}
	
	/**
	 * Adds an output format to the job.
	 * 
	 * @param outputFormat the output format key
	 * @return <code>true</code> if the ouput was not already present in the job 
	 * @see #setOutputFormats(Set)
	 */
	public boolean addOutputFormat(byte outputFormat) {
		return outputFormats.add(new Byte(outputFormat));
	}
	
	/**
	 * Removes an output format from the job.
	 * 
	 * @param outputFormat the key of the output format to remoce
	 * @return <code>true</code> if the output format was present in the job
	 */
	public boolean removeOutputFormat(byte outputFormat) {
		return outputFormats.remove(new Byte(outputFormat));
	}

	/**
	 * Returns the owner of this job.
	 * 
	 * <p>
	 * The job owner is automatically determined from the context when the job
	 * is scheduled.
	 * For new/unsaved jobs, the owner will be <code>null</code>. 
	 * </p>
	 * 
	 * @return the username of the job owner
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * Sets the owner of this job.
	 * 
	 * <p>
	 * This method should not be called by code that schedules jobs as the job
	 * owner is automatically set when the job is saved, overwriting any existing
	 * value.
	 * </p>
	 * 
	 * @param username the job owner
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * Returns the code of the locale which will be used to execute the report.
	 * 
	 * <p>
	 * </p>
	 * 
	 * @return the report job locale, or <code>null</code> if none set
	 * @see #setOutputLocale(String)
	 */
	public String getOutputLocale() {
		return outputLocale;
	}

	/**
	 * Sets a locale to be used to execute the report.
	 * 
	 * <p>
	 * The report output will be localized according to the provided locale.
	 * </p>
	 * 
	 * @param outputLocale the locale code as in <code>java.util.Locale.toString()</code>
	 */
	public void setOutputLocale(String outputLocale) {
		this.outputLocale = outputLocale;
	}

    /**
     * Compares two report jobs
     *
     *
     * @param rj the ReportJob wich compares to this one
     * @return <code>true</code> if both report jobs are equal
     */
    public boolean equals(ReportJob rj) {
        return
          this.label.equals(rj.getLabel()) &&
          this.username.equals(rj.getUsername()) &&
          this.baseOutputFilename.equals(rj.getBaseOutputFilename()) &&
          this.trigger.equals(rj.getTrigger());
    }

}
