/*
ESUP-portail is a french academic project developed under the GPL (General Public License) augmented according to the following :
A binary or source file developped by ESUP-portail can be used or compiled with products under Apache license.
The official english text of the GPL can be found here : http://www.gnu.org/licenses/gpl.html .
A non official french translation can be found here : http://www.linux-France.org/article/these/gpl.html .
The different kinds of licenses governing the products developed by the Apache foundation can be found here : http://www.apache.org/licenses .
It follows that you can as well as use download contents as well modify and redistribute them provided you respect the GPL terms.
Downloading and using such contents do not provide any guaranty.
Be sure that you have well understood the terms of the license before using the contents it covers.
The ESUP-portail distribution includes the following distributions :
    * UPortal :
      software developed by JA-SIG (Java Architecture - Special Interest Group)
      You can find the license page here : http://mis105.udel.edu/ja-sig/uportal/license.html
    * CAS :
      SSO solution developed by Yale University
      You can find the project page here : http://www.yale.edu/tp/auth
    * Cocoon :
      XML framework distributed by the Apache foundation under Apache license;
      Please find the full text here : http://cocoon.apache.org/2.1/license.html
    * Mod_dav:
      A DAV module for Apache web server
      You can find the project page here : http://www.webdav.org/mod_dav
    * IMP :
      webmail from Horde application framework
      You can find the project page here : http://www.horde.org
    * …. To be completed
*/
package org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.parse;

import java.text.SimpleDateFormat;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.MetaDataConstants;
import org.esupportail.portal.channels.CStockage.exception.ApplicationException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedException;
import org.esupportail.portal.channels.CStockage.exception.NotExistsResourceException;
import org.esupportail.portal.channels.CStockage.provider.ChannelResource;
import org.esupportail.portal.channels.CStockage.provider.access.ServerAccess;



/**
 * Id: RequiredMetaData.java,v 1.0 9 juil. 2004<br/>
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)<br/>
 * Classes: RequiredMetaData<br/>
 * Original Author: Yohan Colmant<br/>
 * This represents a required metadata on an injac document<br/>
 */
public class RequiredMetaData {

	
	private static final String REQUIRED_TRUE = "yes";
	private static final String REQUIRED_FALSE = "no";
	
	public static final String LEVEL_EDITION = "edition";
	public static final String LEVEL_PUBLICATION = "publication";
	
	public static final String INPUT_TEXT = "text";
	public static final String INPUT_TEXTAREA = "textarea";
	public static final String INPUT_SELECT = "select";
	
	public static final String TYPE_STRING = "string";
	public static final String TYPE_DATE = "date";
	
	public static final String DEFAULT_DATE_FORMAT = "dd/MM/yyyy";
	
	
	
	/**
	 * The MD name
	 */
	private String name;
	
	/**
	 * The MD label
	 */
	private String label;
	
	/**
	 * The MD input type
	 */
	private String input;
	
	/**
	 * The MD type
	 */
	private String type;
	
	/**
	 * The MD choice list
	 */
	private String choicelist;
	
	/**
	 * The choice list into an array
	 */
	private String[] choiceListArray;
	
	/**
	 * The MD required value: yes, no
	 */
	private String requiredData;
	
	/**
	 * The MD level: edition, publication
	 */
	private String level;
	
	/**
	 * The default value
	 */
	private String value;
	
	/**
	 * The comment
	 */
	private String comment;
	
	/**
	 * The format used to check if the MD is good
	 */
	private String format;
	
	
	
	/**
	 * The userChoice
	 */
	private String userChoice;
	
	
	/**
	 * If the metadata if modifiable
	 */
	private boolean modifiable = true;
	
	
	
	/**
	 * Default constructor
	 *
	 */
	public RequiredMetaData() {		
	}
	
	
	/**
	 * @return Returns the modifiable.
	 */
	public boolean isModifiable() {
		return modifiable;
	}
	/**
	 * @param modifiable The modifiable to set.
	 */
	public void setModifiable(boolean modifiable) {
		this.modifiable = modifiable;
	}
	
	
	
	/**
	 * @return Returns the userChoice.
	 */
	public String getUserChoice() {
		return userChoice;
	}
	/**
	 * @param userChoice The userChoice to set.
	 */
	public void setUserChoice(String userChoice) {
		this.userChoice = userChoice;
	}
	
	
	
	/**
	 * Check if the user set is valid or not
	 * @return true if valid, false else
	 */
	public boolean isValid() {
		
		// if not required
		if (!isRequired()) {
			
			if (getValue().trim().equals("")) {
				return true;
			}
			else {
				return answerIsInGoodFormat();
			}
		}
		
		// if required
		else {			
			return answerIsInGoodFormat();			
		}
			
	}
	
	
	/**
	 * Check if the user answer is in the good format
	 * @return true if yes, false if no
	 */
	private boolean answerIsInGoodFormat() {
		

		if (value == null || value.equals(""))
			return false;
		
		
		if (format == null)
			return true;
		if (format.trim().equals(""))
			return true;
		
		else { 
			// check the format
			
			// if string
			if (type != null && type.equals(TYPE_STRING)) {
				Pattern modele = Pattern.compile(getFormat());
		        Matcher correspondance = modele.matcher(getValue());
		        if(correspondance.matches())
		            return true;
		        else
		            return false;
			}
			
			// if date
			else if (type != null && type.equals(TYPE_DATE)) {
				
				try {
					SimpleDateFormat sdf = new SimpleDateFormat(getFormat());
					if (sdf==null) {
						return false;
					}
					else {
						sdf.parse(getValue());
					}
				}
				catch(Exception e) {
					return false;
				}
				
			}
			
			
			return true;
		}
	}
	
	
	/**
	 * @return Returns the input.
	 */
	public String getInput() {
		return input;
	}
	/**
	 * @return Returns the comment.
	 */
	public String getComment() {
		if (comment == null)
			return "";
		else return comment;
	}
	/**
	 * @return Returns the defaultValue.
	 */
	public String getValue() {
		if (value == null)
			return "";
		else return value;
	}
	/**
	 * @return Returns the format.
	 */
	public String getFormat() {
		return format;
	}
	/**
	 * @return Returns the label.
	 */
	public String getLabel() {
		return label;
	}
	/**
	 * @return Returns the level.
	 */
	public String getLevel() {
		return level;
	}
	/**
	 * @return Returns the name.
	 */
	public String getName() {
		return name;
	}
	/**
	 * @return Returns the required.
	 */
	public boolean isRequired() {
				
		if (requiredData == null)
			return false;
		
		if (requiredData.equals(REQUIRED_TRUE))
			return true;
		else return false;
	}
	/**
	 * @return Returns the type.
	 */
	public String getType() {
		return type;
	}
	
	/**
	 * Return the choice list in a string array format
	 * @return the choice list in a string array format
	 */
	public String[] getChoiceList() {
		
		if (choicelist == null)
			return null;
		
		if (choiceListArray==null) {
			
			StringTokenizer strToken = new StringTokenizer(choicelist, ",");
			choiceListArray = new String[strToken.countTokens()];
			
			for (int i=0; strToken.hasMoreTokens(); i++) {
				choiceListArray[i] = strToken.nextToken();
			}
			
		}
		
		return choiceListArray;
	}
	
	
	
	
	
	/**
	 * @param choicelist The choicelist to set.
	 */
	public void setChoicelist(String choicelist) {		
		this.choicelist = choicelist;
	}
	/**
	 * @param comment The comment to set.
	 */
	public void setComment(String comment) {		
		this.comment = comment;
	}
	/**
	 * @param value The value to set.
	 */
	public void setValue(String value) {
		this.value = value;
	}
	/**
	 * @param format The format to set.
	 */
	public void setFormat(String format) {
		this.format = format;
	}
	/**
	 * @param label The label to set.
	 */
	public void setLabel(String label) {
		this.label = label;
	}
	/**
	 * @param level The level to set.
	 */
	public void setLevel(String level) {
		this.level = level;
	}
	/**
	 * @param name The name to set.
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @param requiredData The required to set.
	 */
	public void setRequiredData(String requiredData) {		
		this.requiredData = requiredData;
	}
	/**
	 * @param isRequired The isRequired to set.
	 */
	public void setRequiredData(boolean isRequired) {		
		if (isRequired)
			this.requiredData = REQUIRED_TRUE;
		else this.requiredData = REQUIRED_FALSE;		
	}
	/**
	 * @param type The type to set.
	 */
	public void setType(String type) {		
		this.type = type;
	}
	/**
	 * @param input The input to set.
	 */
	public void setInput(String input) {		
		this.input = input;
	}
	
	
	
	
	
	/**
	 * Get a default RequiredMetaData object for the "reject-cause" MD
	 * @return a default RequiredMetaData object for the "reject-cause" MD
	 */
	public static RequiredMetaData getNewRejectCauseMetatada() {
		RequiredMetaData md = new RequiredMetaData();
		
		md.setName(MetaDataConstants.REJECT_CAUSE);
		md.setLabel(MetaDataConstants.REJECT_CAUSE);
		md.setInput(INPUT_TEXTAREA);
		md.setType(TYPE_STRING);
		md.setRequiredData(REQUIRED_FALSE);
		md.setLevel(LEVEL_PUBLICATION);			
		
		return md;
	}
		
	

	
	/**
	 * Get the RequiredMetaData object for the "root-file-name" MD for the specified path
	 * @return the RequiredMetaData object for the "root-file-name" MD for the specified path
	 */
	public static RequiredMetaData getNewRootFileNameMetatada(ServerAccess access, String path, String name, boolean owner) throws NotExistsResourceException, ApplicationException, NotAuthorizedException {
		RequiredMetaData rootFileNameMD = new RequiredMetaData();
		
		String choiceList = "";
		if (access.isDirectory(name, path)) {
			ChannelResource[] list = access.ls(path+name);
			for (int i=0; list!=null && i<list.length; i++) {			
				if (!list[i].isCollection()) {			
					choiceList += list[i].getDisplayName();
					if (i!=list.length-1) {
						choiceList += ",";
					}
				}
			}
		}
		else {
			choiceList = name;
		}
		
		
		rootFileNameMD.setChoicelist(choiceList);
		rootFileNameMD.setInput(RequiredMetaData.INPUT_SELECT);
		rootFileNameMD.setLevel(RequiredMetaData.LEVEL_EDITION);
		rootFileNameMD.setName(MetaDataConstants.ROOT_FILE_NAME);
		rootFileNameMD.setLabel(MetaDataConstants.ROOT_FILE_NAME);
		rootFileNameMD.setRequiredData(true);
		rootFileNameMD.setType(RequiredMetaData.TYPE_STRING);		
		
		if (owner) {
			rootFileNameMD.setModifiable(true);
		}
		else {
			rootFileNameMD.setModifiable(false);
		}
		
		return rootFileNameMD;
	}
	
	

	/**
	 * Get the RequiredMetaData object for the "root-file-name" MD for the specified path
	 * @return the RequiredMetaData object for the "root-file-name" MD for the specified path
	 */
	public static RequiredMetaData getNewRootFileNameMetatada(String name, boolean owner) throws NotExistsResourceException, ApplicationException, NotAuthorizedException {
		RequiredMetaData rootFileNameMD = new RequiredMetaData();
		
		String choiceList = name;
		
		rootFileNameMD.setChoicelist(choiceList);
		rootFileNameMD.setInput(RequiredMetaData.INPUT_SELECT);
		rootFileNameMD.setLevel(RequiredMetaData.LEVEL_EDITION);
		rootFileNameMD.setName(MetaDataConstants.ROOT_FILE_NAME);
		rootFileNameMD.setLabel(MetaDataConstants.ROOT_FILE_NAME);
		rootFileNameMD.setRequiredData(true);
		rootFileNameMD.setType(RequiredMetaData.TYPE_STRING);
		
		if (owner) {
			rootFileNameMD.setModifiable(true);
		}
		else {
			rootFileNameMD.setModifiable(false);
		}
		
		return rootFileNameMD;
	}
	
	
	/**
	 * Get a default RequiredMetaData object for the "publication-date-begin" MD
	 * @return a default RequiredMetaData object for the "publication-date-begin" MD
	 */
	public static RequiredMetaData getNewPublicationDateBeginMetatada() {
		RequiredMetaData md = new RequiredMetaData();
		
		md.setName(MetaDataConstants.PUBLICATION_DATE_BEGIN);
		md.setLabel(MetaDataConstants.PUBLICATION_DATE_BEGIN);
		md.setInput(INPUT_TEXT);
		md.setType(TYPE_DATE);
		md.setRequiredData(REQUIRED_FALSE);
		md.setLevel(LEVEL_PUBLICATION);			
		md.setFormat(DEFAULT_DATE_FORMAT);
		
		return md;
	}
	
	
	/**
	 * Get a default RequiredMetaData object for the "publication-date-end" MD
	 * @return a default RequiredMetaData object for the "publication-date-end" MD
	 */
	public static RequiredMetaData getNewPublicationDateEndMetatada() {
		RequiredMetaData md = new RequiredMetaData();
		
		md.setName(MetaDataConstants.PUBLICATION_DATE_END);
		md.setLabel(MetaDataConstants.PUBLICATION_DATE_END);		
		md.setInput(INPUT_TEXT);
		md.setType(TYPE_DATE);
		md.setRequiredData(REQUIRED_FALSE);
		md.setLevel(LEVEL_PUBLICATION);			
		md.setFormat(DEFAULT_DATE_FORMAT);
		
		return md;
	}
	
	
	/**
	 * Clone this object
	 */
	public Object clone() {
		RequiredMetaData clone = new RequiredMetaData();
		
		clone.name = this.name;
		clone.label = this.label;
		clone.input = this.input;
		clone.type = this.type;
		clone.choicelist = this.choicelist;
		clone.requiredData = this.requiredData;
		clone.level = this.level;
		clone.value = this.value;
		clone.comment = this.comment;
		clone.format = this.format;
		clone.userChoice = this.userChoice;
		clone.modifiable = this.modifiable;
		
		return clone;
	}
	
	
	
	/**
	 * Return a String representation of this RequiredMetaData
	 * @return a String representation of this RequiredMetaData
	 */
	public String toString() {
		return
		"RequiredMetaData: "+name+"\n"+
		"                  label: "+label+"\n"+
		"                  type: "+type+"\n"+
		"                  choiceList: "+choicelist+"\n"+
		"                  required: "+requiredData+"\n"+
		"                  level: "+level+"\n"+
		"                  value: "+value+"\n"+
		"                  comment: "+comment+"\n"+
		"                  format: "+format+"\n"+
		"                  modifiable: "+modifiable+"\n";
	}
	
	
}
