package lu.tudor.santec.gecamed.formeditor.gui.model;

import java.awt.Color;
import java.awt.Font;
import java.awt.font.TextAttribute;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.controller.document.DocumentController;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialog;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialogImpl;
import lu.tudor.santec.gecamed.core.utils.AutoEncodingFileReader;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.formeditor.ejb.entity.beans.Form;
import lu.tudor.santec.gecamed.formeditor.ejb.entity.beans.FormTemplate;
import lu.tudor.santec.gecamed.formeditor.ejb.entity.beans.FormValue;
import lu.tudor.santec.gecamed.formeditor.ejb.session.beans.FormManagerImpl;
import lu.tudor.santec.gecamed.formeditor.ejb.session.interfaces.FormManager;
import lu.tudor.santec.gecamed.formeditor.gui.FormEditorModule;
import lu.tudor.santec.gecamed.formeditor.gui.FormWidgets;
import lu.tudor.santec.gecamed.formeditor.gui.component.BackgroundPanel;
import lu.tudor.santec.gecamed.formeditor.gui.component.EditableComponent;
import lu.tudor.santec.gecamed.formeditor.gui.component.EditableSubForm;
import lu.tudor.santec.gecamed.formeditor.gui.controller.FormController;
import lu.tudor.santec.gecamed.formeditor.gui.controller.converter.HistoryHtmlHandler;
import lu.tudor.santec.gecamed.formeditor.gui.exception.InvalidSubFormIdException;
import lu.tudor.santec.gecamed.formeditor.gui.view.FormTab;
import lu.tudor.santec.gecamed.letter.gui.placeholders.PlaceholdersConfig;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Incident;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.IncidentManagerBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IncidentManager;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.CellConstraints.Alignment;
import com.jgoodies.forms.layout.FormLayout;
import com.l2fprod.common.demo.Main;


/**
 * @author ferringj
 *
 */
public class FormModel 
{
	public static final String STARTING_VERSION_NO = "0.1";
	
	public static final byte TYPE_EDITOR 			= 0;
	public static final byte TYPE_PREVIEW 			= 1;
	public static final byte TYPE_FORM 				= 2;
	public static final byte TYPE_EDITOR_SUBFORM 	= 3;
	
	public static final String NONE = "none";
	
//	public static final String FORM_ENTRY_TYPE = "form"; 
//	public static final String REPORT_TEMPLATE_TYPE = "form_template";
	
	public static final int ADD_JCOMPONENT = 0;
	public static final int ADD_EDITABLE_COMPONENT = 1;
	
//	private static final String HEAD_TAG = "<head>";
	
	
	
	private static Logger 		logger = Logger.getLogger(FormModel.class.getName());
	
	private static FormManager 	formManager;

	private FormTemplate 	template;
	private Form 			form;
	private FormTab 		formTab;
	private EditableSubForm	subForm;
	private String 			version = STARTING_VERSION_NO;
	private String 			colSpec;
	private String 			rowSpec;
	private String 			initScript;
	private StringBuffer 	functions_compressed;
	private BackgroundPanel view;
	private JScrollPane 	viewScrollPane;
	private JLabel 			tabLabel;
	private boolean 		modified;
	private boolean 		loaded;
	private boolean			isBeingModified = false;
	private byte 			type;
	private Date 			newCreationDate;
	
	private HistoryHtmlHandler 				historyHandler;
	private Map<String, JComponent> 		components;
	private Map<String, JComponent> 		globalComponents;
	private Map<String, EditableComponent> 	editableComponents;
	private Map<String, String> 			functions;
	private HashMap<Object, Object> 		formContext = new HashMap<Object, Object>();
	private HashMap<Object, Object> 		globalContext;
	
	private DatabaseReferences dbRef = new DatabaseReferences(null);
//	private List<FormDatabaseChangedListener> databaseListener = new ArrayList<FormDatabaseChangedListener>();

	
	public FormModel(byte type) 
	{
		this.type = type;
		
		template = new FormTemplate();
		template.setName("");
		template.setDescription("");
	}
	
	/**
	 * changes the instance with the information given in the parameter
	 * 
	 * @param colSpec
	 *            the new definition for the FormLayout-columns
	 * @param rowSpec
	 *            the new definition for the FormLayout-rows
	 * @param components
	 *            the component, the model shell own
	 * @param initScript
	 *            the script, that is executed, after the model is created
	 * @param functions
	 *            the functions, that can be referenced in the scripts
	 */
	public void changeModel(String colSpec, String rowSpec, byte[] background,
			Map<String, EditableComponent> components, String initScript,
			Map<String, String> functions) 
	{
		EditableComponent 	ec;
		JComponent 			c;
		JPanel 				componentPanel;
		
		isBeingModified = true;
		
		// create the view, to be added somewhere
		this.colSpec = colSpec.replaceFirst(colSpec.substring(0, colSpec.indexOf(",")), "0px");
		this.rowSpec = rowSpec.replaceFirst(rowSpec.substring(0, rowSpec.indexOf(",")), "0px");

		// create view with scroll pane
		if (view == null)
			view = new BackgroundPanel();
		view.removeAll();
		view.setLayout(new FormLayout(colSpec, rowSpec));
		view.setBackgroundImage(background);
		view.addMouseWheelListener(EditableComponent.scrollingListener);
		view.setBackgroundImageX(0);
		view.setBackgroundImageY(0);
		view.setBackgroundImageWidth(-1);
		view.setBackgroundImageHeight(-1);
		view.setOpaque(true);
		view.setBackground(GECAMedColors.c_GECAMedBackground);
		
		if (viewScrollPane == null)
		{
			viewScrollPane = new JScrollPane(view);
			viewScrollPane.getVerticalScrollBar().setUnitIncrement(16);
			viewScrollPane.setOpaque(true);
			viewScrollPane.getViewport().setBackground(GECAMedColors.c_GECAMedBackground);
			viewScrollPane.setBackground(GECAMedColors.c_GECAMedBackground);
		}
		
		this.components 		= new HashMap<String, JComponent>();
		this.globalComponents 	= new HashMap<String, JComponent>();
		
		// add the components to the view and map
		if (initScript != null) {
			this.initScript = initScript;
		} else {
			initScript = "";
		}

		this.functions = functions;
		functions_compressed = new StringBuffer();
		for (String function : functions.values()) 
		{
			this.functions_compressed.append(function).append(FormWidgets.NEWLINE);
		}

		this.editableComponents = new HashMap<String, EditableComponent>();
//		editableComponents = components;
		
		for (String key : components.keySet()) 
		{
			ec = components.get(key);
			if (ec != null) 
			{
				if (isPreview() || isForm())
				{
					c = ec.copyComponent(this);
					componentPanel = ec.getAddablePanel(c);
					
					this.view.add(componentPanel, ec.getConstraints().clone());
					
					ec.copyLayout(c, componentPanel);
				}
				else 
				{
					c = ec.getComponent();
					if (this.isSubForm())
						this.view.add(ec, ec.getConstraints().clone());
				}
				
				this.editableComponents.put	(ec.getKey(), ec);
				this.components.put			(key, c);
				this.globalComponents.put	(key, c);
				if (ec instanceof EditableSubForm)
				{
					this.globalComponents.putAll(((EditableSubForm) ec).getSubComponentMap(key));
					((EditableSubForm) ec).setParentFormModel(this);
				}
			}
		}
		
		isBeingModified = false;
		view.setOpaque(false);
	}

	/**
	 * get a FormModel instance with the information in the parameter. Use
	 * this instead of new FormModel(...)
	 * 
	 * @param colSpec
	 *            the new definition for the FormLayout-columns
	 * @param rowSpec
	 *            the new definition for the FormLayout-rows
	 * @param components
	 *            the component, the model shell own
	 * @param initScript
	 *            the script, that is executed, after the model is created
	 * @param functions
	 *            the functions, that can be referenced in the scripts
	 * @return an new FormModel instance
	 */
	public static FormModel getInstance(String colSpec, String rowSpec, byte[] background,
			Map<String, EditableComponent> components, String initScript,
			Map<String, String> functions, byte type) 
	{
		FormModel model = new FormModel(type);
		model.changeModel(colSpec, rowSpec, background, components, initScript,
				functions);
		return model;
	}
	
	
	public void close ()
	{
		if (editableComponents == null)
			return;
		
		for (EditableComponent ec : editableComponents.values())
		{
			ec.dispose();
		}
	}
	

	/***********************************************
	 ************** GETTER AND SETTER **************
	 **********************************************/

	public Integer getId() {
		return (template != null ? template.getId() : null);
	}

	public void executeInitMethod() 
	{
		this.loaded = false;
		for (EditableComponent ec : editableComponents.values())
		{
			if (ec != null && ec instanceof EditableSubForm)
			{
				((EditableSubForm)ec).setParentFormModel(this);
				((EditableSubForm)ec).executeInitMethod();
			}
		}
		
		new FormController(this).executeCodeAt(initScript, null);
		this.loaded = true;
	}

	public String getFunctionsAsOneString() {
		return functions_compressed.toString();
	}

	public Collection<String> getFunctions() {
		return functions.values();
	}
	
	public Map<String, JComponent> getComponents() {
		return components;
	}
	
	public Map<String, JComponent> getGlobalComponents () 
	{
		return globalComponents;
	}

	public JScrollPane getView() {
		return viewScrollPane;
	}
	
	public BackgroundPanel getPanel() {
		return view;
	}

	public void setName(String name) {
		template.setName(name);
	}

	public String getName() {
		return template.getName();
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String versionNo) {
		version = versionNo;
	}
	
	public String getDescription() {
		return template.getDescription();
	}
	
	public void setDescription (String description) {
		template.setDescription(description);
	}
	
	public DatabaseReferences getDBReferences () 
	{
		dbRef.setTemplate(this.template);
		return dbRef;
	}
	
	
	public boolean isLoaded ()
	{
		return loaded;
	}

	public Map<String, EditableComponent> getEditableComponents() {
		return editableComponents;
	}

	public Map<String, String> getFunctionMap() {
		return functions;
	}

	public String getInitScript() {
		return initScript;
	}

	public String getColSpec() {
		return colSpec;
	}

	public String getRowSpec() {
		return rowSpec;
	}

	public void setTemplate(FormTemplate template) 
	{
		this.template = template;
		dbRef.setTemplate(this.template);
	}

	public FormTemplate getTemplate() {
		return template;
	}

	public void setForm(Form form) {
		this.form = form;
	}

	public Form getForm() {
		return form;
	}
	
	public Date getDateCreated () {
		if (newCreationDate == null) {
			newCreationDate = new Date(form.getDateCreated().getTime());
		}
		
		return newCreationDate;
	}
	
	public void setDateCreated (Date date) {
		newCreationDate = date;
	}
	
	public boolean hasDateCreatedChanged () {
		return !getDateCreated().equals(form.getDateCreated());
	}

	public void setModified(boolean modified) 
	{
		if (this.modified != modified)
		{
			if (formTab != null) 
			{
				if (!modified && this.modified) 
				{
					// notifies all the components of this form, that this form was saved
					for (EditableComponent ec : this.editableComponents.values()) 
						ec.saved();
				}
				
				this.modified = modified;
				
				if (modified) 
				{
					formTab.setModified(true);
					if (!tabLabel.getText().endsWith(" *</html>")
							&& !tabLabel.getText().endsWith(" *"))
						if (tabLabel.getText().startsWith("<html>"))
							 tabLabel.setText(tabLabel.getText().replace("</html>", " *</html>"));
						else tabLabel.setText(tabLabel.getText() + " *");
				}
				else tabLabel.setText(tabLabel.getText().replace(" *", ""));
			}
			else if (isSubForm() && subForm.getParentFormModel() != null)
				subForm.getParentFormModel().setModified(modified);
		}
	}

	public boolean isModified() {
		return modified;
	}
	
	public boolean isBeingModified ()
	{
		return isBeingModified;
	}

	public void setFormTab(FormTab tab, JLabel tabLabel) {
		this.formTab  = tab;
		this.tabLabel = tabLabel;
	}

	public FormTab getFormTab() {
		if (subForm != null && subForm.getParentFormModel() != null)
			 return subForm.getParentFormModel().getFormTab();
		else return formTab;
	}
	
	public void setSubForm (EditableSubForm subForm)
	{
		this.subForm = subForm;
	}
	
	public EditableSubForm getSubForm ()
	{
		return subForm;
	}
	
	public boolean isSubForm ()
	{
		return subForm != null; // && subForm.getParentFormModel() != null;
	}
	
	public HashMap<Object, Object> getFormContext() {
		return formContext;
	}
	
	public HashMap<Object, Object> getGlobalContext() {
		if (globalContext == null)
		{
			if (isSubForm())
				 globalContext = subForm.getParentFormModel().getGlobalContext();
			else globalContext = new HashMap<Object, Object>();
		}
		return globalContext;
	}
	
	
	private static FormManager getFormManager ()
	{
		if (formManager == null) {
			formManager = (FormManager) ManagerFactory.getRemote(FormManagerImpl.class);
		}
		return formManager;
	}
	

	/******************************************
	 ******* LOAD, SAVE, EXPORT, IMPORT *******
	 *****************************************/
	
	/**
	 * stores a template of this FormModel in the DB under the specified
	 * name
	 * 
	 * @param name
	 *            the name, under which the template will be saved
	 */
	public void saveTemplate(Integer toBeReplacedTemplateId) {
		/* ======================================== */
		// get a XMLDocument from this FormModel
		Document doc = convertModelToXML();
		
		// get the XML-string
		String xml = "";
		StringWriter writer = new StringWriter();
		XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
		try {
			/* ---------------------------------------- */
			xmlOutputter.output(doc, writer);
			xml = writer.toString();
			/* ---------------------------------------- */
		} catch (IOException e) {
			logger.log(Level.ERROR, "Error converting document to XML: " + e.getLocalizedMessage(), (Throwable)e);
			return;
		}
		
		// configure the template and this FormModel
		/*
		 * template != null -> template was loaded from the DB
		 * replacedTemplate != null -> there is another template, with the
		 * same name, that should be replaced
		 */
		if (template == null) {
			// create a new template and init it with the data of this
			// FormModel
			template = new FormTemplate();
		}

		/* replace the id, to override the replacedTemplate. 
		 * If the ID is null a new template will be created.
		 */
		template.setId(toBeReplacedTemplateId);
//			template.setName(name);
		template.setVersion(getVersion());
		template.setXml(xml);
//			template.setDescription(description);

		// save the template
		// get a FormManager from the server
		FormManager manager = getFormManager();
		
		template = manager.saveTemplateWithoutIReport(template);
		/* ======================================== */
	}
	
	public static FormModel createNewForm (FormModel model, FormTemplate template, Patient patient) {
		
		model.setTemplate(template);
		
		Form f = new Form();
		f.setTemplateId(template.getId());
		f.setPatientId(patient.getId());
		FormWidgets.addFormEntryForCurrentIncident(f);
		
		
		model.setForm(f);
		
		model.setIncidentEntryDescription(model.getName());
		
		return model;
	}
	
	
	public void save() 
	{
		boolean 	createIncident 	= form.getSubForm() == null;
		String 		description 	= "";
		FormManager manager 		= getFormManager();
		
		try {
			if (createIncident)
			{
				try 
				{
					description = getIncidentDescription();
				}
				catch (Exception e)
				{
					logger.log(Level.WARN, "Could not create the incident description.", e);
				}
				setIncidentEntryDescription(description);
			}
			
			boolean creationDateChanged = this.hasDateCreatedChanged();
			if (creationDateChanged) {
				/* ---------------------------------------- */
				/* the date of the form has changed, the incident and the incident entry
				 * need to be adapted
				 */
				form.setDateCreated(getDateCreated());
				if (createIncident)
					changeIncidentEntryCreationDate();
				/* ---------------------------------------- */
			}
			
			Form savedForm = manager.saveForm(form);
			
			if (savedForm == null) 
			{
				// the form was deleted by another user, since it was opened by this user
				/* ------------------------------ */
				String oldKey = FormTab.getKeyForForm(form);
				
				int buttonPressed = GECAMedBaseDialogImpl.showMessageDialog(formTab, 
						Translatrix.getTranslationString("formeditor.formNotFound_title"), 
						Translatrix.getTranslationString("formeditor.formNotFound_msg"), 
						GECAMedBaseDialogImpl.YES_NO_BUTTON_MODE);
				
				if (buttonPressed == GECAMedBaseDialog.YES_OPTION) 
				{
					/* ----------  save under a new entry  ---------- */
					// TODO: isn't proper working, yet
					
					// create a new form and save it to get an ID
					Form f = new Form();
					f.setTemplateId(form.getTemplateId());
					f = manager.saveForm(f);
					/* **************************************** */

					// define the form values
					Collection<FormValue> newValues = f.getValues();
					if (newValues == null) {
						f.setValues(new LinkedList<FormValue>());
						newValues = f.getValues();
					} else {
						newValues.clear();
					}
					
					for (FormValue value : form.getValues()) {
						value.setFormId(f.getId());
						newValues.add(value);
					}
					/* **************************************** */
					
					// store the changes
					FormWidgets.addFormEntryForCurrentIncident(f);
					this.setForm(f);
					setIncidentEntryDescription(description);
					this.setForm(manager.saveForm(this.getForm()));
					
					// if the form is null, something didn't work
					if (this.getForm() == null) {
						try {
							throw new Exception ("NOT SAVED EXCEPTION!!!");
						} catch (Exception e) {
							logger.log(Level.ERROR, e.getMessage(), e);
							formTab.closeFormWithoutSaving(oldKey);
							return;
						}
					}
					
					String newKey = FormTab.getKeyForForm(form);
					
					formTab.switchTabKey(oldKey, newKey);
					this.setModified(false);
					
				} 
				else 
				{
					/* -----  close it without saving  ----- */
					formTab.closeFormWithoutSaving(oldKey);
				}
				return;
			}
			setForm(savedForm);
			
			this.setModified(false);
		} 
		catch (Exception e) 
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
		
		if (createIncident)
			PatientManagerModule.getInstance().getPatientPanel().reloadHistory();
	}
	
	
	/**
	 * Gathers the description and the value of all components that shell
	 * be shown in the history - formated in html.
	 * (if the value of the component is empty, it isn't shown in the history)
	 * 
	 * @param formTitle
	 * 		The Title of the template is the headline of the description
	 * @param components
	 * 		All EditableComponents of the form
	 * @return
	 * 		the description that will be shown in the history for this form
	 */
	public String getIncidentDescription() 
	{
		StringBuffer description 	= new StringBuffer();
		String 		 templateName 	= template.getName();
//		String 		 htmlText;
		
		if (historyHandler == null)
			historyHandler = new HistoryHtmlHandler(this);
		
		try
		{
			// get the HTML history text for this form
			description.append(historyHandler.createHistoryHtml());
			
//			// replace all unnecessary 
//			htmlText = htmlText.replaceAll("(\\w|\\W)*\\<(?i)html(?-i)[^\\>]*\\>", "");
//			htmlText = htmlText.replaceAll("\\<(?i)head(?-i)[^\\>]*(\\w|\\W)*\\</(?i)head(?-i)\\>", "");
//			htmlText = htmlText.replaceAll("\\</(?i)html(?-i)\\>(\\w|\\W)*", "</html>");
//			htmlText = htmlText.trim();
//			
//			// create an HTML head including the title
//			description.append("<head><title>")
//				.append(templateName)
//				.append("</title></head>")
//				.append(htmlText);
		}
		catch (Exception e)
		{
//			// create a description with just the name of the form
//			description.append("<head><title>")
//					.append(templateName)
//					.append("</title></head><b>")
//					.append(templateName);
			description.append(templateName);
			// the error message is already shown just throw the warning ...
			logger.log(Level.WARN, e.getMessage(), e);
		}
		
		return validateHtml(description.toString());
	}
	
	
	private String validateHtml (String html)
	{
		return "<html>" + 
				html.replaceAll("\\<html[^\\>]+\\>", "")
					.replaceFirst("^.*\\<html", "<html")
					.replaceAll("\\<![^\\>]*\\>", "")
					.replaceAll("\\<((?i)meta) [^\\>]*\\>", "");
	}
	
	
	public void setIncidentEntryDescription(String description) 
	{
		IncidentEntry entry;
		
		if (form.getIncidentEntry() == null) 
		{
			// the entry does not exist
			FormWidgets.addFormEntryForCurrentIncident(form);
		}
		
		entry = form.getIncidentEntry();
		entry.setTextContent(description);
		entry.setCode(String.valueOf(template.getId()));
	}
	
	public void changeIncidentEntryCreationDate () {
		IncidentManager incidentManager = (IncidentManager) ManagerFactory.getRemote(IncidentManagerBean.class);
		
		changeIncidentEntryCreationDate(this.form, incidentManager);
		
		if (formTab != null) {
			this.tabLabel.setText(formTab.getTabName(this));
		}
		
		incidentManager.deleteNullIncident(GECAMedModule.getCurrentPatient().getId());
	}
	
	public static void changeIncidentEntryCreationDate (Form form, IncidentManager incidentManager) 
	{
		// change the creation date of the incident entry
		form.getIncidentEntry().setCreated(form.getDateCreated());
		
		if (incidentManager == null) 
			incidentManager = (IncidentManager) ManagerFactory.getRemote(IncidentManagerBean.class);
		
		/* Get an incident that was created between the creation date 
		 * of the incident entry and 4 hours before or create a new one
		 */
		Calendar olderThan = new GregorianCalendar();
		Calendar newerThan = new GregorianCalendar();
		olderThan.setTime(form.getDateCreated());
		newerThan.setTime(form.getDateCreated());
		newerThan.set(Calendar.HOUR, newerThan.get(Calendar.HOUR) - 4);
		
		Incident inc = PatientManagerModule.getInstance().getPatientPanel().getIncidentAtATimePoint(
				true, newerThan, olderThan);
		
		form.getIncidentEntry().setIncident(inc);
		form.getIncidentEntry().setIncidentId(inc.getId());
		form.setIncidentEntry(incidentManager.saveEntry(form.getIncidentEntry(), FormTab.NAME));
	}

	/**
	 * loads an empty object of the form with the specified name. Over the
	 * model you can get the view, a JPanel, that you can add somewhere.
	 * 
	 * @param templateId
	 *            the id under which the template can be found
	 * @param globalModule
	 *            needed to make the components in the editor draggable. Can
	 *            be null if not opened in FormEditorModule
	 * @return returns the new FormModel
	 */
	public void loadTemplate(int templateId, FormEditorModel globalModel) {
		/* ======================================== */
		// load a FormManager object from the server
		FormManager manager = getFormManager();

		// use the manager to load the template with the specified id
		FormTemplate template = manager.getTemplate(templateId);

		loadTemplate(template, globalModel, false);
		/* ======================================== */
	}

	public void loadTemplate(FormTemplate template,
			FormEditorModel globalModel, boolean replace) 
	{
		try {
			// get the XML form the object and create a XMLDocument from it
			String xml;
			
//			if (globalModel == null) {
			if (replace 
					&& GECAMedModule.getCurrentPatient() 		 != null
					&& GECAMedModule.getCurrentPatient().getId() != null) {
				xml = replacePlaceholders(template.getXml());
			} else {
				xml = template.getXml();
			}
			
			StringReader 	reader 	= new StringReader(xml);
			SAXBuilder 		builder = new SAXBuilder();
			Document 		doc 	= builder.build(reader);

			// convert the XML to a FormModel
			convertXMLToModel(doc, globalModel);

			// save the template to make sure to save changes on the same
			// template and don't create a new one
			this.setTemplate(template);
		} catch (JDOMException e) {
			logger.log(Level.ERROR, e.getMessage(), e);
		} catch (IOException e) {
			logger.log(Level.ERROR, e.getMessage(), e);
		}
	}
	
	private static String replacePlaceholders (String text)
	{
		HashMap<String, Vector<String>> categoryMap = PlaceholdersConfig.getOldPlaceHolderNames();
		Set<String> categorSet = categoryMap.keySet();
		List<String> placeholdersOfCategory;
		String replacementText;
		
		for (String category : categorSet)
		{
			placeholdersOfCategory = categoryMap.get(category);
			for (String placeholder : placeholdersOfCategory)
			{
				if (text.contains(placeholder))
				{
					replacementText = PlaceholdersConfig.getValue(placeholder, category, DocumentController.PH_VERSION_OLD);
					text = text.replaceAll(placeholder, replacementText);
				}
			}
		}
		
		return text;
	}
	

	public void load(Form form, boolean isAPreview) 
	{
		this.setForm(form);
		load((FormEditorModel)null, isAPreview);
	}

	
	public void load(boolean isAPreview) 
	{
		load((FormEditorModel)null, isAPreview);
	}
	
	
	public void load(FormEditorModel globalModel, boolean isAPreview) 
	{
		this.loaded = false;
		
		if (template == null) 
		{
			// if template wasn't set, load from the DB
			FormManager manager = getFormManager();
			template = manager.getTemplate(form.getTemplateId());
		}
		
		// initialize the FormModel with the specified template
		loadTemplate(template, globalModel, true);
		
		// load values
		if (form != null) 
		{
			Collection<FormValue> values = form.getValues();
			if (values != null) 
			{
				// load the values of the form into the Components
				LinkedList<String> valueKeys = new LinkedList<String>();
				for (FormValue value : values) 
				{
					valueKeys.add(value.getKey());
					EditableComponent ec = editableComponents.get(value.getKey());
					if (ec != null && ec.isStoredInDB()) 
					{
						/* only if the component is supposed to be stored, 
						 * it is supposed to be loaded again (for the case,
						 * the value was stored but shouldn't be stored anymore)
						 */
						ec.setText(value.getValue());
					}
				}
				
				// add the MISSING_VALUE for those components, that weren't stored in the db
				for (EditableComponent ec : editableComponents.values()) 
					if (ec.isStoredInDB()
							&& !valueKeys.contains(ec.getKey()))
						ec.setText(EditableComponent.MISSING_VALUE);
			}
		}
		
		this.loaded = true;
	}

	public boolean importTemplate(File file, FormEditorModel globalModel) 
	{
		File					schemaFile;
		Schema					schema;
		AutoEncodingFileReader	encoder	= null;
		InputStreamReader		isr;
		Document				doc;
		
		
		try 
		{
			encoder		= new AutoEncodingFileReader(file);
			isr			= encoder.read();
			
			/*
			 * validate document
			 */
			schemaFile	= FormWidgets.getFile(FormEditorModule.class, "form.xsd");
			schema		= SchemaFactory.newInstance(
					XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(
					new StreamSource(schemaFile));
			schema.newValidator().validate(new StreamSource(isr));
			
			// build the document
			isr			= encoder.read();
			doc			= new SAXBuilder().build(isr);
			
			// create a model out of the document
			convertXMLToModel(doc, globalModel);
			return true;
		}
		catch (Exception e) 
		{
			GECAMedBaseDialogImpl.showMessageDialog(globalModel.getView(),
					Translatrix.getTranslationString("formeditor.validation_error_title"), 
					Translatrix.getTranslationString("formeditor.validation_error")
							+ "<br><br>" 
							+ e.getMessage(), 
					GECAMedBaseDialogImpl.OK_BUTTON_MODE);
			logger.log(Level.INFO, "Importing of form failed, because of following reason: ", e);
			return false;
		}
		finally
		{
			if (encoder != null)	encoder.closeStream();
		}
	}

	
	public void exportTemplate(File file)
	{
		Document			doc = convertModelToXML();
		XMLOutputter		xml = new XMLOutputter(Format.getPrettyFormat());
		FileOutputStream	fos	= null;
		OutputStreamWriter	osw = null;
		String				oldPath;
		
		
		try
		{
			if (file.exists())
			{
				/*
				 * if the file already exists, create a backup of the
				 * existing file, before overwriting it
				 */
				oldPath	= file.getAbsolutePath();
				file.renameTo(new File(oldPath.replaceAll("\\.((?i)xml)$", "_backup.xml")));
				file	= new File(oldPath);
			}
			
			/*
			 * if the file not exists, it has to be created, if it existed,
			 * it was renamed and has to be recreated
			 */
			file.createNewFile();
			
			// write the xml document into the file
			fos	= new FileOutputStream(file);
			osw	= new OutputStreamWriter(fos, "UTF-8");
			xml.output(doc, osw);
			osw.close();
			fos.close();
		}
		catch (FileNotFoundException e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
		catch (IOException e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
		finally
		{
			try
			{
				if (fos != null) fos.close();
				if (osw != null) osw.close();
			}
			catch (IOException e)
			{
				logger.log(Level.ERROR, e.getMessage(), e);
			}
		}
	}
	
	
	public void saveStructure (String structure, String componentKey) 
	{
		FormManager 	manager 	= getFormManager();
		FormTemplate 	template 	= manager.getTemplate(this.template.getId());
		
		try {
			Document doc = new SAXBuilder().build(new StringReader(template.getXml()));
			List<?> components = doc.getRootElement().getChildren("component");
			
			for (Object o : components) {
				Element componentElem = (Element)o;
				
				if (componentElem.getAttribute("key").getValue().equals(componentKey)) 
				{
					Element structureElem = componentElem.getChild("structure");
					structureElem.setText(structure);
					
					StringWriter xml = new StringWriter();
					XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
					xmlOutputter.output(doc, xml);
					
					template.setXml(xml.toString());
					
					manager.saveTemplateWithoutIReport(template);
					break;
				}
			}
		} 
		catch (JDOMException e) 
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		} 
		catch (IOException e) 
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
	}

	/*******************************
	 ******** XML-CONVERTER ********
	 ******************************/

	@SuppressWarnings("unchecked")
	public void convertXMLToModel(Document doc, FormEditorModel globalModel) 
	{
		// the ROOT element
		String errorMsg = "";
		try {
			Element root 		= doc.getRootElement();
			String 	name 		= root.getAttributeValue("name");
			String 	version 	= root.getAttributeValue("version");
			boolean subFormOnly = Boolean.parseBoolean(root.getAttributeValue("subFormOnly"));
			String 	description = root.getChildText("description");
			String 	initScript 	= root.getChildText("initScript");
			Element layout 		= root.getChild("layout");
			String 	colSpec 	= layout.getChildText("colFormat");
			String 	rowSpec 	= layout.getChildText("rowFormat");
			String 	imgData 	= layout.getChildText("backgroundImg");

			EditableComponent 	editableComponent;
			Class<?> 			objClass;
			
			Element element;
			Color 	color;
			String 	key;
			String 	elementText;
			byte[] 	backgroundBytes = null;
			int 	col;
			int 	row;
			int 	colSize;
			int 	rowSize;
			int 	eventId;
			Integer size;

			List<Element> components 	= root.getChildren("component");
			List<Element> elements;
			
			HashMap<String, EditableComponent> 	editableComponents = new HashMap<String, EditableComponent>();
			Map<TextAttribute, Object> 			attributes;
			
			if (imgData != null && !imgData.isEmpty()) {
				backgroundBytes = FormWidgets.base64ToBytes(imgData);
			}
			
//			int index = 0;
			// COMPONENTS
			
			for (Element xmlComponent : components) 
			{
				key 		= xmlComponent.getAttributeValue("key");
				col 		= Integer.parseInt(xmlComponent.getAttributeValue("xCoord"));
				row 		= Integer.parseInt(xmlComponent.getAttributeValue("yCoord"));
				colSize 	= Integer.parseInt(xmlComponent.getAttributeValue("xSize"));
				rowSize 	= Integer.parseInt(xmlComponent.getAttributeValue("ySize"));
				
				try {
					// create an EditableComponent and add it into the map.
					// the key at first, so it can be called, if the
					// ClassLoader throws an Exception
					elementText 		= xmlComponent.getChildText("type");
					objClass 			= Class.forName(elementText, true, Main.class.getClassLoader());
					
					editableComponent 	= (EditableComponent) objClass.newInstance();
					editableComponent.init(new CellConstraints(col, row, colSize, rowSize), globalModel, this.type);
					editableComponent.setOpaque(false);
					// ((JPanel)comp).setForeground(Color.white);
					// comp.setComponentBackground(Color.white);
					if (isEditor())
						editableComponent.setName(col + ":" + row);
					else 
						editableComponent.setName(key);
					
					elementText = xmlComponent.getChildText("structure");
					try 
					{
						editableComponent.setStructure(elementText);
						editableComponent.setStartStructure(editableComponent.getStructure());
						
						editableComponent.setText(xmlComponent.getAttributeValue("value"));
	//					comp.setStartText(comp.getText());
					}
					catch (InvalidSubFormIdException isfe)
					{
						logger.log(Level.INFO, isfe.getMessage());
					}
					// add the component with the specified key
					editableComponent.setKeyDo(key);
					
					editableComponent.setStoreInDB(FormWidgets.parseBool(
							xmlComponent.getAttributeValue("storeInDB"), null));
					
					/* **********  ADDED FOR HISTORY  ********** */
					editableComponent.setShowInHistory(FormWidgets.parseBool(
							xmlComponent.getAttributeValue("showInHistory"), false));
					editableComponent.setHistoryIndex(FormWidgets.parseFloat(
							xmlComponent.getAttributeValue("historyIndex"), 0.0f));
					editableComponent.setDescriptionPosition(
							xmlComponent.getAttributeValue("labelPosition"));
					editableComponent.setDescription(xmlComponent.getAttributeValue("labelText"));
					/* **************************************** */
					
					/* **********  LAYOUT DEFINITION  ********** */
					// BORDER
					elementText = xmlComponent.getChildText("border");
					editableComponent.getPropertyPanel().setPaintBorder(getIsPainted(elementText));
					editableComponent.getPropertyPanel().setBorderColor(getColor(elementText));
					editableComponent.getPropertyPanel().paintBorder();
					
					
					// BACKGROUND
					elementText = xmlComponent.getChildText("background");
					
					color = getColor(elementText);
					if (color != null) 
						editableComponent.setComponentBackground(color);
					
					editableComponent.setComponentOpaq(getIsPainted(elementText));
					
					// 	-- FONT: --
					attributes = (Map<TextAttribute, Object>) 
							editableComponent.getComponentForProperty().getFont().getAttributes();
					
					// FONT STYLE
					elementText = xmlComponent.getChildText("fontStyle");
					
					if (elementText != null) {
						
						if (elementText.contains("b")) 
							 attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
						else attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
						
						if (elementText.contains("i")) 
							 attributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
						else attributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
						
						if (elementText.contains("u")) 
							 attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
						else attributes.put(TextAttribute.UNDERLINE, -1);
					}
					
					// FONT SIZE
					elementText = xmlComponent.getChildText("fontSize");
					if (elementText != null) 
					{
						try {
							size = Integer.parseInt(elementText);
//							comp.changeFont(TextAttribute.SIZE, size);
							attributes.put(TextAttribute.SIZE, size);
						} 
						catch (NumberFormatException e) 
						{
							// do nothing and keep the default settings
						}
					}
					
					
					// FONT FAMILY
					elementText = xmlComponent.getChildText("fontFamily");
					
					if (elementText != null) 
						attributes.put(TextAttribute.FAMILY, elementText);
					
					
					// FONT COLOR
					elementText = xmlComponent.getChildText("fontColor");
					color 		= getColor(elementText);
					
					if (color != null) 
						attributes.put(TextAttribute.FOREGROUND, color);
//						comp.changeFont(TextAttribute.FOREGROUND, foregroundColor);
					
					editableComponent.setFont(new Font(attributes));
					
					
					// HORIZONTAL ALIGNMENT
					elementText = xmlComponent.getChildText("hAlign");
					editableComponent.getConstraints().hAlign = getAlignment(elementText);
					
					
					// VERTICAL ALIGNENT
					elementText = xmlComponent.getChildText("vAlign");
					editableComponent.getConstraints().vAlign = getAlignment(elementText);
					/* **************************************** */
					
					editableComponents.put(key, editableComponent);
					// put the code for the listener method to the specified
					// position in the code-array
					
					elements = xmlComponent.getChildren("script");
					for (Iterator<Element> i = elements.iterator(); i.hasNext(); ) 
					{
						element = i.next();
						eventId = Integer.parseInt(element.getAttributeValue("eventTypeId"));
						elementText = element.getChildText("scriptCode");
						editableComponent.setFormulaAt(eventId, elementText);
					}
				} catch (Exception e) {
					logger.log(Level.ERROR, e.getMessage(), e);
				}
			}

			// FUNCTIONS
			HashMap<String, String> functionMap = new HashMap<String, String>();
			String 	functionName;
			String 	functionScript;
			
			elements = root.getChildren("function");
			for (Iterator<Element> iter = elements.iterator(); iter.hasNext();) 
			{
				element = iter.next();
				functionName = element.getAttributeValue("name");
				functionScript = element.getChildText("scriptCode");
				functionMap.put(functionName, functionScript);
			}
			
			// Create a FormModel based on the data collected from the
			// xml-file.
			// int addOption = globalModel == null ? ADD_EDITABLE_COMPONENT
			// : ADD_JCOMPONENT;
			this.changeModel(colSpec, rowSpec, backgroundBytes, editableComponents, initScript, functionMap);
			setName(name);
			this.template.setSubFormOnly(subFormOnly);
			setDescription(description);
			setVersion(version);
		} 
		catch (Exception e) 
		{
			logger.log(Level.ERROR, e.getMessage(), e);
			if (errorMsg.length() == 0) 
			{
				errorMsg = "An error occured: The XML in invalid.\n" + 
						e.getMessage();
			}
			if (globalModel != null) 
			{
				GECAMedBaseDialogImpl.showMessageDialog(globalModel.getView(),
						Translatrix.getTranslationString("formeditor.error"),
						errorMsg, GECAMedBaseDialogImpl.OK_BUTTON_MODE);
			} 
			else 
			{
				logger.log(Level.ERROR, e.getMessage(), e);
			}
		}
	}

	public Document convertModelToXML() {
		/* ======================================== */
		// the root element, containing all the other elements
		Element root = new Element("form");
		
		root.setAttribute("info", "Form template of " + 
				System.getProperty("APP_NAME") + " " + 
				System.getProperty("APP_VERSION") +
				" - This file is a template to create forms for GECAMed " +
				"(GEstion de CAbinet Medicaux).");
		root.setAttribute("name", template.getName());
		root.setAttribute("version", getVersion());
		root.setAttribute("subFormOnly", String.valueOf(template.isSubFormOnly()));
		
		Element description = new Element("description");
		description.addContent(getDescription());
		
		root.addContent(description);
//			root.setAttribute("description", template.getDescription());

		// the layout for the panel
		Element layout = new Element("layout");
		Element colFormat = new Element("colFormat");
		colFormat.addContent(colSpec.replaceAll(" ", ""));
		layout.addContent(colFormat);
		
		Element rowFormat = new Element("rowFormat");
		rowFormat.addContent(rowSpec.replaceAll(" ", ""));
		layout.addContent(rowFormat);
		
		Element backgroundImg = new Element("backgroundImg");
		backgroundImg.addContent(FormWidgets.bytesToBase64(view.getBackgroundImageBytes()));
		layout.addContent(backgroundImg);
		
		root.addContent(layout);
		
		// the components to be entered into the panel
		Element component;
		for (String key : editableComponents.keySet()) {
			/* ---------------------------------------- */
			/* **********  COMPONENT ATTRIBUTES  ********** */
			EditableComponent ec = editableComponents.get(key);
			component = new Element("component");
			component.setAttribute("xCoord", 	String.valueOf(ec.getColumn()));
			component.setAttribute("yCoord", 	String.valueOf(ec.getRow()));
			component.setAttribute("xSize", 	String.valueOf(ec.getColumnWidth()));
			component.setAttribute("ySize", 	String.valueOf(ec.getRowHeight()));
			component.setAttribute("key", 		key);
			component.setAttribute("value", 	ec.getText());
			component.setAttribute("storeInDB", String.valueOf(ec.isStoredInDB()));
			
			/* ----------  ADDED FOR HISTORY  ---------- */
			component.setAttribute("showInHistory", String.valueOf(ec.isShowInHistory()));
			component.setAttribute("historyIndex", 	String.valueOf(ec.getHistoryIndex()));
			component.setAttribute("labelPosition", ec.getDescriptionPosition());
			component.setAttribute("labelText", 	ec.getDescription());
			/* ---------------------------------------- */
			/* **************************************** */
			
			
			/* **********  COMPONENT CONTENT  ********** */
			
			/* ----------  BASIC COMPONENT CONTENT  ---------- */
			// TYPE
			Element type = new Element("type");
			type.addContent(ec.getClass().getName());
			component.addContent(type);
			
			// SCRIPT
			Element scriptElement;
			String 	script;
			for (int index = 0; index < ec.getFormulaSize(); index++) 
			{
				scriptElement = new Element("script");
				script = ec.getScriptAt(index);
				if (script != null && !(script.length() == 0)) 
				{
					scriptElement.setAttribute("eventTypeId", index + "");
					Element scriptCode = new Element("scriptCode");
					scriptCode.addContent(script);
					scriptElement.addContent(scriptCode);
					component.addContent(scriptElement);
				}
			}
			
			// STRUCTURE
			Element structure = new Element("structure");
			structure.addContent(ec.getStructure());
			component.addContent(structure);
			/* ---------------------------------------- */
			
			
			/* ----------  LAYOUT DEFINITION  ---------- */
			ec.resetComponentBackground();
			
			JComponent propertyComponent = ec.getComponentForProperty();
			
			// BORDER
			Color borderColor = ec.getPropertyPanel().getBorderColor();
			if (borderColor == null) {
				borderColor = Color.BLACK;
			}
			Element border = new Element("border");
			border.addContent(new StringBuilder()
					.append(ec.getPropertyPanel().isPaintBorder()).append(",")
					.append(borderColor.getRed()).append(",")
					.append(borderColor.getGreen()).append(",")
					.append(borderColor.getBlue()).append(",")
					.append(borderColor.getAlpha()).toString());
			component.addContent(border);
			
			
			// BACKGROUND
			Color backgroundColor = ec.getComponentBackground();
			if (backgroundColor == null) {
				backgroundColor = Color.WHITE;
			}
			Element background = new Element("background");
			background.addContent(new StringBuilder()
					.append(ec.getPropertyPanel().isPaintBackground()).append(",")
					.append(backgroundColor.getRed()).append(",")
					.append(backgroundColor.getGreen()).append(",")
					.append(backgroundColor.getBlue()).append(",")
					.append(backgroundColor.getAlpha()).toString());
			component.addContent(background);

			
			// 	-- FONT: --
			Map<TextAttribute, ?> attributes = propertyComponent.getFont().getAttributes();
			
			
			// FONT STYLE
			Element fontStyleElement = new Element("fontStyle");
			StringBuilder fontStyle = new StringBuilder();
			if (TextAttribute.WEIGHT_BOLD.equals(
					attributes.get(TextAttribute.WEIGHT))) 
				fontStyle.append("b");
			if (TextAttribute.POSTURE_OBLIQUE.equals(
					attributes.get(TextAttribute.POSTURE))) 
				fontStyle.append("i");
			if (TextAttribute.UNDERLINE_ON.equals(
					attributes.get(TextAttribute.UNDERLINE))) 
				fontStyle.append("u");
			
			fontStyleElement.addContent(fontStyle.toString());
			component.addContent(fontStyleElement);
			
			
			// FONT SIZE
			Element fontSizeElement = new Element("fontSize");
			fontSizeElement.addContent(String.valueOf(propertyComponent.getFont().getSize()));
			component.addContent(fontSizeElement);
			
			
			// FONT FAMILY
			Element fontFamilyElement = new Element("fontFamily");
			fontFamilyElement.addContent(attributes.get(
					TextAttribute.FAMILY).toString());
			component.addContent(fontFamilyElement);
			
			
			// FONT COLOR
			Color foregroundColor = (Color) attributes.get(TextAttribute.FOREGROUND);
			if (foregroundColor != null) {
				/* ---------------------------------------- */
				Element fontColor = new Element("fontColor");
				fontColor.addContent("true" +
						"," + foregroundColor.getRed() +
						"," + foregroundColor.getGreen() +
						"," + foregroundColor.getBlue() +
						"," + foregroundColor.getAlpha());
				component.addContent(fontColor);
				/* ---------------------------------------- */
			}
			
			
			// HORIZONTAL ALIGNMENT
			Element hAlignElement = new Element("hAlign");
			hAlignElement.addContent(ec.getConstraints().hAlign.toString());
			component.addContent(hAlignElement);
			
			
			// VERTICAL ALIGNENT
			Element vAlignElement = new Element("vAlign");
			vAlignElement.addContent(ec.getConstraints().vAlign.toString());
			component.addContent(vAlignElement);
			/* ---------------------------------------- */
			/* **************************************** */
			
			
			root.addContent(component);
			/* ---------------------------------------- */
		}

		// contains the init script
		Element initScript = new Element("initScript");
		initScript.addContent(this.initScript);
		root.addContent(initScript);

		// contains all functions with their names and executable script
		Element function;
		for (String key : this.functions.keySet()) 
		{
			function = new Element("function");
			function.setAttribute("name", key);
			Element e = new Element("scriptCode");
			e.addContent(this.functions.get(key));
			function.addContent(e);
			// function.setAttribute("script", this.functions.get(key));
			root.addContent(function);
		}
		
		return new Document(root);
		/* ======================================== */
	}
	
	
	private static Color getColor (String colorElementString) {
		/* ======================================== */
		if (colorElementString == null) {
			/* ---------------------------------------- */
			return null;
			/* ---------------------------------------- */
		}
		
		String[] colorParts = colorElementString.split(",");
		
		if (colorParts.length > 3) {
			/* ---------------------------------------- */
			Color color;
			
			if (colorParts.length > 4) {
				color = new Color(
						Integer.parseInt(colorParts[1]),
						Integer.parseInt(colorParts[2]),
						Integer.parseInt(colorParts[3]),
						Integer.parseInt(colorParts[4]));
			} else {
				color = new Color(
						Integer.parseInt(colorParts[1]),
						Integer.parseInt(colorParts[2]),
						Integer.parseInt(colorParts[3]));
			}
			return color;
			/* ---------------------------------------- */
		}
		
		return null;
		/* ======================================== */
	}
	
	private static boolean getIsPainted (String colorElementString) {
		/* ======================================== */
		if (colorElementString == null) {
			/* ---------------------------------------- */
			return false;
			/* ---------------------------------------- */
		}
		
		String[] backgroundParts = colorElementString.split(",");
		
		return backgroundParts[0].toUpperCase().equals("TRUE");
		/* ======================================== */
	}
	
	private static Alignment getAlignment (String alignment) {
		/* ======================================== */
		if (alignment == null) {
			return CellConstraints.DEFAULT;
		} else if (alignment.equals(CellConstraints.BOTTOM.toString())) {
			return CellConstraints.BOTTOM;
		} else if (alignment.equals(CellConstraints.CENTER.toString())) {
			return CellConstraints.CENTER;
		} else if (alignment.equals(CellConstraints.FILL.toString())) {
			return CellConstraints.FILL;
		} else if (alignment.equals(CellConstraints.LEFT.toString())) {
			return CellConstraints.LEFT;
		} else if (alignment.equals(CellConstraints.RIGHT.toString())) {
			return CellConstraints.RIGHT;
		} else if (alignment.equals(CellConstraints.TOP.toString())) {
			return CellConstraints.TOP;
		} else {
			return CellConstraints.DEFAULT;
		}
		/* ======================================== */
	}
	
	
	public byte getType ()
	{
		return this.type;
	}
	
	public boolean isEditor ()
	{
		return type == TYPE_EDITOR;
	}
	
	public boolean isPreview ()
	{
		return type == TYPE_PREVIEW;
	}
	
	public boolean isForm ()
	{
		return type == TYPE_FORM;
	}
}
