package semorg.gui;

import java.sql.SQLException;
import java.sql.Timestamp;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;

import semorg.gui.list.CompanyListWindow;
import semorg.gui.util.AssociationTabControl;
import semorg.gui.util.CalendarControl;
import semorg.gui.util.ForeignKeyConstraintSelector;
import semorg.gui.util.ItemListener;
import semorg.gui.util.Messages;
import semorg.gui.util.CalendarControl.SWTCalendarEvent;
import semorg.gui.util.CalendarControl.SWTCalendarListener;
import semorg.sql.tables.AbstractTable;
import semorg.sql.tables.Booking;
import semorg.sql.tables.Client;
import semorg.sql.tables.Company;
import semorg.sql.tables.Enumeration;
import semorg.sql.util.Utility;

/** The window for editing new or existing company records. */
public class CompanyWindow {

    /**
     * Inner class which provides a listener reacting on changes of the input in
     * the {@link CompanyWindow} window.
     */
    class InputChangedListener implements ModifyListener, SelectionListener,
	    SWTCalendarListener, ItemListener {

	/**
	 * Appends to the title of the window an asterisk (*) if the input has
	 * changed. Furthermore it sets the flag {@link #inputChanged} to
	 * <tt>true</tt>.
	 */
	private void inputChanged() {
	    if (!settingInput && !inputChanged) {
		inputChanged = true;
		shell.setText(shell.getText() + "*");
	    }
	}

	/** Invokes {@link #inputChanged()} if a text has been changed. */
	public void modifyText(ModifyEvent e) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a widget has been selected. */
	public void widgetSelected(SelectionEvent e) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a doubleclick has occurred. */
	public void widgetDefaultSelected(SelectionEvent e) {
	    inputChanged();
	}

	/** Invokes {@link #inputChanged()} if a date has been changed. */
	public void dateChanged(SWTCalendarEvent event) {
	    inputChanged();
	}

	/**
	 * Invokes {@link #inputChanged()} if a item in the
	 * AssociationTabControl has changed.
	 */
	public void itemChanged() {
	    inputChanged();
	}
    }

    /**
     * Holds the data of the actual displayed data record. If a new record is
     * entered it is set to <tt>null</tt> until the changes have been
     * committed.
     */
    private Company input;

    /**
     * Is set to <tt>true</tt> if the data from the database (or corresponding
     * from {@link #input}) is to be set into the window form, otherwise
     * <tt>false</tt>. <br>
     * <br>
     * 
     * That is needed to prevent the {@link ModifyListener} from firing when the
     * data is load into the window form by using the .setText() methods of the
     * GUI elements.
     */
    private boolean settingInput = false;

    /**
     * Is set to <tt>true</tt> if the input has been changed and not committed
     * yet, otherwise it is set to <tt>false</tt>.
     */
    private boolean inputChanged;

    /**
     * <tt>true</tt> if the editing of the input (i.e. the elements of the
     * form) has been enabled, otherwise it is <tt>false</tt>. <br>
     * <br>
     * 
     * This flag indicates whether the actual displayed record has been locked
     * by the actual editing window or not. This avoids the releasing of records
     * which are locked by other editing windows.
     */
    private boolean inputEditingEnabled;

    /** Listener instance added to the most elements of the window. */
    private InputChangedListener inputChangedListener = new InputChangedListener();

    /* ********** GUI PROPERTIES ********* */
    /** The editing window. */
    private Shell shell;
    private int titleBarHeight;

    /* Text- and Combofields, CalendarControls and Buttons */
    private final Label numberLabel;
    private final Text numberText;
    private final Text shortNameText;
    private final Combo salutationCombo;
    private final Combo titleCombo;
    private final Text firstNameText;
    private final Text nameText;
    private final Text streetText;
    private final Text zipCodeText;
    private final Text cityText;
    private final Combo countryCombo;
    private final Combo annexCombo;
    private final Text phoneText;
    private final Text mobileText;
    private final Text faxText;
    private final Text emailText;
    private final Combo cpSalutationCombo;
    private final Combo cpTitleCombo;
    private final Text cpFirstNameText;
    private final Text cpNameText;
    private final Text cpPhoneText;
    private final Text cpMobileText;
    private final Text cpFaxText;
    private final Text cpEmailText;
    private final Text cpDepartmentText;
    private final Text cpTaskText;
    private final CalendarControl customerSinceCalendar;
    private final CalendarControl cpBirthDayCalendar;
    private final Text turnoverText;
    private final Text shortMessageText;
    private final Text memoText;

    /**
     * The control widget to manage the association employee between
     * {@link Client} and {@link Company}.
     */
    private AssociationTabControl employeeControl;

    /**
     * The control widget to manage the association between {@link Company} and
     * {@link Booking} (and its subclasses).
     */
    private AssociationTabControl bookingsControl;

    private final Button okButton;
    private final Button applyButton;
    private final Button newButton;
    private final Button abortButton;

    /** The triangle-button with the apex to the left. */
    private final Button prevButton;
    /** The triangle-button with the apex to the right. */
    private final Button nextButton;

    /**
     * Creates a {@link CompanyWindow} instance with the given shell as the
     * parent shell. <br>
     * <br>
     * 
     * It also adds a listener which reacts on closing events. It checks if
     * changes have been made and if so it opens a dialog which informs the user
     * and asks for a decision (confirm/discard). Finally it releases the locked
     * record (if one is displayed and it is locked by this editing window).
     * 
     * @param parent
     *                Shell instance used the as parent shell of the window.
     */
    private CompanyWindow(Shell parent) {

	shell = new Shell(parent, SWT.CLOSE);

	shell.addListener(SWT.Close, new Listener() {
	    public void handleEvent(Event event) {
		if (inputChanged) {
		    if (confirmClose()) {
			if (inputEditingEnabled && input != null)
			    Company.lockedIds
				    .remove(new Integer(input.getId()));
		    } else
			event.doit = false;
		} else if (input != null && inputEditingEnabled)
		    Company.lockedIds.remove(new Integer(input.getId()));
	    }
	});

	shell.setLayout(new GridLayout(1, false));
	shell.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
	shell.setSize(700, 630);
	shell.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CompanyWindow");

	GridData mgd = new GridData();
	mgd.horizontalAlignment = GridData.FILL;
	mgd.verticalAlignment = GridData.BEGINNING;
	mgd.grabExcessHorizontalSpace = true;

	final Group mainForm = new Group(shell, SWT.NULL);
	mainForm.setLayoutData(mgd);
	mainForm.setLayout(new GridLayout(2, false));

	final TabFolder tabs = new TabFolder(shell, SWT.FLAT);
	tabs.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "Tabs");
	GridData tgd = new GridData();
	tgd.horizontalAlignment = GridData.FILL;
	tgd.verticalAlignment = GridData.BEGINNING;
	tgd.grabExcessHorizontalSpace = true;
	tabs.setLayoutData(tgd);

	final Composite leftColumn = new Composite(mainForm, SWT.NULL);
	leftColumn.setLayout(new GridLayout(1, false));
	GridData lcgd = new GridData();
	lcgd.widthHint = 370;
	lcgd.horizontalAlignment = GridData.FILL;
	lcgd.grabExcessHorizontalSpace = true;
	lcgd.verticalAlignment = GridData.BEGINNING;
	leftColumn.setLayoutData(lcgd);

	final Composite rightColumn = new Composite(mainForm, SWT.NULL);
	rightColumn.setLayout(new GridLayout(1, false));
	GridData rightColumnGridData = new GridData();
	rightColumnGridData.horizontalAlignment = GridData.FILL;
	rightColumnGridData.verticalAlignment = GridData.BEGINNING;
	rightColumnGridData.grabExcessHorizontalSpace = true;
	rightColumn.setLayoutData(rightColumnGridData);

	final Composite idComp = new Composite(leftColumn, SWT.NULL);
	idComp.setLayout(new GridLayout(2, false));
	numberLabel = new Label(idComp, SWT.READ_ONLY);
	numberLabel.setText(Messages.getString("GUIText.NumberText"));

	numberText = new Text(idComp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
	numberText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "NumberText");
	Utility.setLength(numberText, 10);
	numberText.addModifyListener(inputChangedListener);

	Label shortNameLabel = new Label(idComp, SWT.READ_ONLY);
	shortNameLabel.setText(Messages.getString("GUIText.CompanyShortName"));

	shortNameText = new Text(idComp, SWT.SINGLE | SWT.BORDER);
	shortNameText
		.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "ShortNameText");
	shortNameText.setBackground(Utility.LIGHT_YELLOW);
	shortNameText.addFocusListener(Utility.checkEmptyListener);
	Utility.setLength(shortNameText, 10);
	shortNameText.addModifyListener(inputChangedListener);

	final Group companyNameField = new Group(leftColumn, SWT.NULL);
	companyNameField.setText(Messages.getString("GUIText.NameFieldText"));
	companyNameField.setLayout(new GridLayout(2, false));
	GridData nameFieldGridData = new GridData();
	nameFieldGridData.horizontalAlignment = GridData.FILL;
	nameFieldGridData.grabExcessHorizontalSpace = true;
	companyNameField.setLayoutData(nameFieldGridData);

	final Group contactField = new Group(rightColumn, SWT.NULL);
	contactField.setText(Messages.getString("GUIText.ContactFieldText"));
	contactField.setLayout(new GridLayout(2, false));
	GridData contactFieldGridData = new GridData();
	contactFieldGridData.horizontalAlignment = GridData.FILL;
	contactFieldGridData.grabExcessHorizontalSpace = true;
	contactField.setLayoutData(contactFieldGridData);

	TabItem contactPersonTab = new TabItem(tabs, SWT.NULL);
	contactPersonTab.setText(Messages
		.getString("GUIText.ContactPersonText"));
	final Composite contactPersonTabComposite = new Composite(tabs,
		SWT.NULL);
	contactPersonTab.setControl(contactPersonTabComposite);
	contactPersonTabComposite.setLayout(new GridLayout(2, false));
	GridData contactPersonTabGridData = new GridData();
	contactPersonTabGridData.verticalAlignment = GridData.BEGINNING;
	contactPersonTabGridData.horizontalAlignment = GridData.FILL;
	contactPersonTabGridData.grabExcessHorizontalSpace = true;
	contactPersonTabComposite.setLayoutData(contactPersonTabGridData);

	Composite cpLeftColumn = new Composite(contactPersonTabComposite,
		SWT.NULL);
	cpLeftColumn.setLayout(new GridLayout(1, false));
	GridData cpLeftColumnGridData = new GridData();
	cpLeftColumnGridData.widthHint = 360;
	cpLeftColumnGridData.verticalAlignment = GridData.BEGINNING;
	cpLeftColumn.setLayoutData(cpLeftColumnGridData);

	Composite cpRightColumn = new Composite(contactPersonTabComposite,
		SWT.NULL);
	cpRightColumn.setLayout(new GridLayout(1, false));
	GridData cpRightColumnGridData = new GridData();
	cpRightColumnGridData.horizontalAlignment = GridData.FILL;
	cpRightColumnGridData.grabExcessHorizontalSpace = true;
	cpRightColumn.setLayoutData(cpRightColumnGridData);

	final Group cpNameField = new Group(cpLeftColumn, SWT.NULL);
	cpNameField.setText(Messages.getString("GUIText.NameFieldText"));
	cpNameField.setLayout(new GridLayout(2, false));
	GridData contactNameFieldGridData = new GridData();
	contactNameFieldGridData.horizontalAlignment = GridData.FILL;
	contactNameFieldGridData.grabExcessHorizontalSpace = true;
	cpNameField.setLayoutData(contactNameFieldGridData);

	final Group cpContactField = new Group(cpRightColumn, SWT.NULL);
	cpContactField.setText(Messages
		.getString("GUIText.ContactPersonContactText"));
	cpContactField.setLayout(new GridLayout(2, false));
	GridData cpContactFieldGridData = new GridData();
	cpContactFieldGridData.horizontalAlignment = GridData.FILL;
	cpContactFieldGridData.grabExcessHorizontalSpace = true;
	cpContactField.setLayoutData(cpContactFieldGridData);

	final Composite additionalComponents = new Composite(rightColumn,
		SWT.NULL);
	additionalComponents.setLayout(new GridLayout(2, false));

	final Composite cpAdditionalComponents = new Composite(cpRightColumn,
		SWT.NULL);
	cpAdditionalComponents.setLayout(new GridLayout(2, false));

	final Label salutationLabel = new Label(companyNameField, SWT.READ_ONLY);
	Utility.alignRight(salutationLabel);
	salutationLabel.setText(Messages.getString("GUIText.SalutationText"));

	Composite nameRowCompletion = new Composite(companyNameField, SWT.NULL);
	GridLayout rcgl = new GridLayout(3, false);
	rcgl.marginWidth = 0;
	rcgl.marginHeight = 0;
	nameRowCompletion.setLayout(rcgl);

	salutationCombo = new Combo(nameRowCompletion, SWT.DROP_DOWN
		| SWT.BORDER);
	salutationCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"SalutationCombo");
	Enumeration.addSalutationEnums(salutationCombo);
	salutationCombo.setBackground(Utility.LIGHT_YELLOW);
	salutationCombo.addFocusListener(Utility.checkEmptyListener);
	salutationCombo.setTextLimit(13);
	GridData scgd = new GridData();
	scgd.widthHint = 80;
	salutationCombo.setLayoutData(scgd);
	salutationCombo.setToolTipText(Messages
		.getString("GUIText.SalutationToolTip"));
	salutationCombo.addModifyListener(inputChangedListener);

	final Label titleLabel = new Label(nameRowCompletion, SWT.READ_ONLY);
	titleLabel.setText(Messages.getString("GUIText.TitelText"));

	titleCombo = new Combo(nameRowCompletion, SWT.DROP_DOWN | SWT.BORDER);
	titleCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "TitleCombo");
	Enumeration.addTitleEnums(titleCombo);
	Utility.setLength(titleCombo, 13);
	titleCombo.setToolTipText(Messages.getString("GUIText.TitelToolTip"));
	titleCombo.addModifyListener(inputChangedListener);

	final Label firstNameLabel = new Label(companyNameField, SWT.READ_ONLY);
	firstNameLabel.setText(Messages.getString("GUIText.FirstNameText"));
	Utility.alignRight(firstNameLabel);

	firstNameText = new Text(companyNameField, SWT.CHECK | SWT.SINGLE
		| SWT.BORDER);
	firstNameText
		.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "FirstNameText");
	Utility.setLength(firstNameText, 30);
	firstNameText.setToolTipText(Messages
		.getString("GUIText.FirstNameToolTip"));
	firstNameText.addModifyListener(inputChangedListener);

	final Label nameLabel = new Label(companyNameField, SWT.READ_ONLY);
	nameLabel.setText(Messages.getString("GUIText.LastNameText"));
	Utility.alignRight(nameLabel);

	nameText = new Text(companyNameField, SWT.SINGLE | SWT.BORDER);
	nameText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "NameText");
	Utility.setLength(nameText, 30);
	nameText.setToolTipText(Messages.getString("GUIText.LastNameToolTip"));
	nameText.setBackground(Utility.LIGHT_YELLOW);
	nameText.addFocusListener(Utility.checkEmptyListener);
	nameText.addModifyListener(inputChangedListener);

	final Group addressField = new Group(leftColumn, SWT.NULL);
	addressField.setText(Messages.getString("GUIText.AdressFieldText"));
	addressField.setLayout(new GridLayout(2, false));
	GridData addressFieldGridData = new GridData();
	addressFieldGridData.horizontalAlignment = GridData.FILL;
	addressFieldGridData.grabExcessHorizontalSpace = true;
	addressField.setLayoutData(addressFieldGridData);

	final Label streetLabel = new Label(addressField, SWT.READ_ONLY);
	streetLabel.setText(Messages.getString("GUIText.StreetText"));
	Utility.alignRight(streetLabel);

	streetText = new Text(addressField, SWT.SINGLE | SWT.BORDER);
	streetText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "StreetText");
	Utility.setLength(streetText, 50);
	streetText.setToolTipText(Messages.getString("GUIText.StreetToolTip"));
	streetText.addModifyListener(inputChangedListener);

	final Label cityLabel = new Label(addressField, SWT.READ_ONLY);
	cityLabel.setText(Messages.getString("GUIText.CityZipCodeText"));
	Utility.alignRight(cityLabel);

	Composite cityRowCompletion = new Composite(addressField, SWT.NULL);
	cityRowCompletion.setLayout(rcgl);

	zipCodeText = new Text(cityRowCompletion, SWT.SINGLE | SWT.BORDER);
	zipCodeText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "ZipCodeText");
	Utility.setLength(zipCodeText, 5);
	zipCodeText
		.setToolTipText(Messages.getString("GUIText.ZipCodeToolTip"));
	zipCodeText.addModifyListener(inputChangedListener);

	cityText = new Text(cityRowCompletion, SWT.SINGLE | SWT.BORDER);
	cityText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CityText");
	Utility.setLength(cityText, 30);
	cityText.setToolTipText(Messages.getString("GUIText.CityToolTip"));
	cityText.addModifyListener(inputChangedListener);

	final Label countryLabel = new Label(addressField, SWT.READ_ONLY);
	countryLabel.setText(Messages.getString("GUIText.CountryText"));
	Utility.alignRight(countryLabel);

	Composite countryRowCompletion = new Composite(addressField, SWT.NULL);
	countryRowCompletion.setLayout(rcgl);

	countryCombo = new Combo(countryRowCompletion, SWT.DROP_DOWN
		| SWT.BORDER);
	countryCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CountryCombo");
	Enumeration.addCountryEnums(countryCombo);
	Utility.setLength(countryCombo, 13);
	countryCombo.addModifyListener(inputChangedListener);
	countryCombo.setToolTipText(Messages
		.getString("GUIText.CountryToolTip"));

	final Label annexLabel = new Label(countryRowCompletion, SWT.READ_ONLY);
	annexLabel.setText(Messages.getString("GUIText.AnnexText"));

	annexCombo = new Combo(countryRowCompletion, SWT.DROP_DOWN | SWT.BORDER);
	annexCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "AnnexCombo");
	Enumeration.addAnnexEnums(annexCombo);
	Utility.setLength(annexCombo, 13);
	annexCombo.setToolTipText(Messages.getString("GUIText.AnnexToolTip"));
	annexCombo.addModifyListener(inputChangedListener);

	final Label phoneLabel = new Label(contactField, SWT.READ_ONLY);
	phoneLabel.setText(Messages.getString("GUIText.PhoneText"));
	Utility.alignRight(phoneLabel);

	phoneText = new Text(contactField, SWT.SINGLE | SWT.BORDER);
	phoneText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "PhoneText");
	Utility.setLength(phoneText, 20);
	phoneText.setToolTipText(Messages.getString("GUIText.PhoneToolTip"));
	phoneText.addModifyListener(inputChangedListener);

	final Label mobileLabel = new Label(contactField, SWT.READ_ONLY);
	mobileLabel.setText(Messages.getString("GUIText.MobileText"));
	Utility.alignRight(mobileLabel);

	mobileText = new Text(contactField, SWT.SINGLE | SWT.BORDER);
	mobileText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "MobileText");
	Utility.setLength(mobileText, 20);
	mobileText.setToolTipText(Messages.getString("GUIText.MobileToolTip"));
	mobileText.addModifyListener(inputChangedListener);

	final Label faxLabel = new Label(contactField, SWT.READ_ONLY);
	faxLabel.setText(Messages.getString("GUIText.FaxText"));
	Utility.alignRight(faxLabel);

	faxText = new Text(contactField, SWT.SINGLE | SWT.BORDER);
	faxText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "FaxText");
	Utility.setLength(faxText, 20);
	faxText.setToolTipText(Messages.getString("GUIText.FaxToolTip"));
	faxText.addModifyListener(inputChangedListener);

	final Label emailLabel = new Label(contactField, SWT.READ_ONLY);
	emailLabel.setText(Messages.getString("GUIText.EmailText"));
	Utility.alignRight(emailLabel);

	emailText = new Text(contactField, SWT.SINGLE | SWT.BORDER);
	emailText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "EmailText");
	Utility.setLength(emailText, 256, 25);
	emailText.setToolTipText(Messages.getString("GUIText.EmailToolTip"));
	emailText.addModifyListener(inputChangedListener);

	Label turnoverLabel = new Label(additionalComponents, SWT.NULL);
	turnoverLabel.setText(Messages.getString("GUIText.TurnOverText"));
	Utility.alignRight(turnoverLabel);

	turnoverText = new Text(additionalComponents, SWT.SINGLE | SWT.BORDER);
	turnoverText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "TurnoverText");
	Utility.setLength(turnoverText, 10);
	turnoverText.addModifyListener(inputChangedListener);
	turnoverText.addFocusListener(Utility.checkCorrectFloatListener);
	turnoverText.setToolTipText(Messages
		.getString("GUIText.TurnOverToolTip"));

	Label customerSinceLabel = new Label(additionalComponents,
		SWT.READ_ONLY);
	customerSinceLabel.setText(Messages
		.getString("GUIText.CustomerSinceText"));
	Utility.alignRight(customerSinceLabel);

	customerSinceCalendar = new CalendarControl(additionalComponents,
		titleBarHeight);
	customerSinceCalendar.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"CustomerSinceCalendar");
	customerSinceCalendar.addSWTCalendarlistener(inputChangedListener);
	customerSinceCalendar.setToolTipText(Messages
		.getString("GUIText.CustomerSinceToolTip"));

	final Label cpSalutationLabel = new Label(cpNameField, SWT.READ_ONLY);
	Utility.alignRight(cpSalutationLabel);
	cpSalutationLabel.setText(Messages.getString("GUIText.SalutationText"));

	Composite contactNameRowCompletion = new Composite(cpNameField,
		SWT.NULL);
	GridLayout cnrcgl = new GridLayout(3, false);
	cnrcgl.marginWidth = 0;
	cnrcgl.marginHeight = 0;
	contactNameRowCompletion.setLayout(cnrcgl);

	cpSalutationCombo = new Combo(contactNameRowCompletion, SWT.DROP_DOWN
		| SWT.BORDER);
	cpSalutationCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"CpSalutationCombo");
	Enumeration.addSalutationEnums(cpSalutationCombo);
	cpSalutationCombo.setBackground(Utility.LIGHT_YELLOW);
	cpSalutationCombo.addFocusListener(Utility.checkEmptyListener);
	cpSalutationCombo.setTextLimit(13);
	GridData cscgd = new GridData();
	cscgd.widthHint = 80;
	cpSalutationCombo.setLayoutData(scgd);
	cpSalutationCombo.setToolTipText(Messages
		.getString("GUIText.SalutationToolTip"));
	cpSalutationCombo.addModifyListener(inputChangedListener);

	final Label cpTitleLabel = new Label(contactNameRowCompletion,
		SWT.READ_ONLY);
	cpTitleLabel.setText(Messages.getString("GUIText.TitelText"));

	cpTitleCombo = new Combo(contactNameRowCompletion, SWT.DROP_DOWN
		| SWT.BORDER);
	cpTitleCombo.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpTitleCombo");
	Enumeration.addTitleEnums(cpTitleCombo);
	Utility.setLength(cpTitleCombo, 13);
	cpTitleCombo.setToolTipText(Messages.getString("GUIText.TitelToolTip"));
	cpTitleCombo.addModifyListener(inputChangedListener);

	final Label cpFirstNameLabel = new Label(cpNameField, SWT.READ_ONLY);
	cpFirstNameLabel.setText(Messages.getString("GUIText.FirstNameText"));
	Utility.alignRight(cpFirstNameLabel);

	cpFirstNameText = new Text(cpNameField, SWT.CHECK | SWT.SINGLE
		| SWT.BORDER);
	cpFirstNameText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"CpFirstNameText");
	Utility.setLength(cpFirstNameText, 30);
	cpFirstNameText.setToolTipText(Messages
		.getString("GUIText.FirstNameToolTip"));
	cpFirstNameText.addModifyListener(inputChangedListener);

	final Label cpNameLabel = new Label(cpNameField, SWT.READ_ONLY);
	cpNameLabel.setText(Messages.getString("GUIText.LastNameText"));
	Utility.alignRight(cpNameLabel);

	cpNameText = new Text(cpNameField, SWT.SINGLE | SWT.BORDER);
	cpNameText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpNameText");
	Utility.setLength(cpNameText, 30);
	cpNameText
		.setToolTipText(Messages.getString("GUIText.LastNameToolTip"));
	cpNameText.setBackground(Utility.LIGHT_YELLOW);
	cpNameText.addFocusListener(Utility.checkEmptyListener);
	cpNameText.addModifyListener(inputChangedListener);

	final Label cpPhoneLabel = new Label(cpContactField, SWT.READ_ONLY);
	cpPhoneLabel.setText(Messages.getString("GUIText.PhoneText"));
	Utility.alignRight(cpPhoneLabel);

	cpPhoneText = new Text(cpContactField, SWT.SINGLE | SWT.BORDER);
	cpPhoneText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpPhoneText");
	Utility.setLength(cpPhoneText, 20);
	cpPhoneText.setToolTipText(Messages.getString("GUIText.PhoneToolTip"));
	cpPhoneText.addModifyListener(inputChangedListener);

	final Label cpMobileLabel = new Label(cpContactField, SWT.READ_ONLY);
	cpMobileLabel.setText(Messages.getString("GUIText.MobileText"));
	Utility.alignRight(cpMobileLabel);

	cpMobileText = new Text(cpContactField, SWT.SINGLE | SWT.BORDER);
	cpMobileText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpMobileText");
	Utility.setLength(cpMobileText, 20);
	cpMobileText
		.setToolTipText(Messages.getString("GUIText.MobileToolTip"));
	cpMobileText.addModifyListener(inputChangedListener);

	final Label cpFaxLabel = new Label(cpContactField, SWT.READ_ONLY);
	cpFaxLabel.setText(Messages.getString("GUIText.FaxText"));
	Utility.alignRight(cpFaxLabel);

	cpFaxText = new Text(cpContactField, SWT.SINGLE | SWT.BORDER);
	cpFaxText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpFaxText");
	Utility.setLength(cpFaxText, 20);
	cpFaxText.setToolTipText(Messages.getString("GUIText.FaxToolTip"));
	cpFaxText.addModifyListener(inputChangedListener);

	final Label cpEmailLabel = new Label(cpContactField, SWT.READ_ONLY);
	cpEmailLabel.setText(Messages.getString("GUIText.EmailText"));
	Utility.alignRight(cpEmailLabel);

	cpEmailText = new Text(cpContactField, SWT.SINGLE | SWT.BORDER);
	cpEmailText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpEmailText");
	Utility.setLength(cpEmailText, 256, 25);
	cpEmailText.setToolTipText(Messages.getString("GUIText.EmailToolTip"));
	cpEmailText.addModifyListener(inputChangedListener);

	final Label cpDepartmentLabel = new Label(cpAdditionalComponents,
		SWT.READ_ONLY);
	cpDepartmentLabel.setText(Messages.getString("GUIText.DepartmentText"));
	Utility.alignRight(cpDepartmentLabel);
	cpDepartmentText = new Text(cpAdditionalComponents, SWT.SINGLE
		| SWT.BORDER);
	cpDepartmentText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"CpDepartmentText");
	Utility.setLength(cpDepartmentText, 30);
	cpDepartmentText.addModifyListener(inputChangedListener);
	cpDepartmentText.setToolTipText(Messages
		.getString("GUIText.DepartmentToolTip"));

	final Label cpBirthDayLabel = new Label(cpAdditionalComponents,
		SWT.READ_ONLY);
	cpBirthDayLabel.setText(Messages.getString("GUIText.BirthdayText"));
	Utility.alignRight(cpBirthDayLabel);

	cpBirthDayCalendar = new CalendarControl(cpAdditionalComponents,
		titleBarHeight);
	cpBirthDayCalendar.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"CpBirthDayCalendar");
	cpBirthDayCalendar.addSWTCalendarlistener(inputChangedListener);
	cpBirthDayCalendar.setToolTipText(Messages
		.getString("GUIText.BirthdayToolTip"));

	final Label cpTaskLabel = new Label(cpAdditionalComponents,
		SWT.READ_ONLY);
	cpTaskLabel.setText(Messages.getString("GUIText.TaskText"));
	Utility.alignRight(cpTaskLabel);
	cpTaskText = new Text(cpAdditionalComponents, SWT.SINGLE | SWT.BORDER);
	cpTaskText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "CpTaskText");
	Utility.setLength(cpTaskText, 30);
	cpTaskText.addModifyListener(inputChangedListener);
	cpTaskText.setToolTipText(Messages.getString("GUIText.TaskToolTip"));

	shortMessageText = Utility.createTextTab(tabs, Messages
		.getString("GUIText.ShortMessageText"), null, 200);
	shortMessageText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"ShortMessageText");
	shortMessageText.addModifyListener(inputChangedListener);
	memoText = Utility.createTextTab(tabs, Messages
		.getString("GUIText.MemoText"), null, 200);
	memoText.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "MemoText");
	memoText.addModifyListener(inputChangedListener);

	TabItem employeeItem = new TabItem(tabs, SWT.NULL);
	employeeItem.setText(Messages.getString("GUIText.EmployeeText"));
	employeeControl = new AssociationTabControl(tabs,
		AssociationTabControl.TYPE_EMPLOYEE, shell);
	employeeControl.addItemListener(inputChangedListener);
	employeeControl.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"EmployeeControl");
	employeeItem.setControl(employeeControl);

	TabItem bokingsItem = new TabItem(tabs, SWT.NULL);
	bokingsItem.setText(Messages.getString("GUIText.CompanyBookingText"));
	bookingsControl = new AssociationTabControl(tabs,
		AssociationTabControl.TYPE_COMPANYBOOKING_COMPANY, shell);
	bookingsControl.addItemListener(inputChangedListener);
	bookingsControl.setData(Utility.ATOSJ_COMPONENT_NAME_KEY,
		"BookingsControl");
	bokingsItem.setControl(bookingsControl);

	final Composite buttons = new Composite(shell, shell.getStyle());
	buttons.setLayout(new GridLayout(7, false));

	okButton = new Button(buttons, SWT.PUSH);
	okButton.setText(Messages.getString("GUIText.OkButtonText"));
	okButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	applyButton = new Button(buttons, SWT.PUSH);
	applyButton.setText(Messages.getString("GUIText.ApplyButtonText"));
	applyButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	newButton = new Button(buttons, SWT.PUSH);
	newButton.setText(Messages.getString("GUIText.NewButtonText"));
	newButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	abortButton = new Button(buttons, SWT.PUSH);
	abortButton.setText(Messages.getString("GUIText.AbortButtonText"));
	abortButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
		| GridData.GRAB_VERTICAL));

	GridData arrowButtonGridData = new GridData();
	arrowButtonGridData.verticalAlignment = GridData.FILL;
	arrowButtonGridData.grabExcessVerticalSpace = true;
	arrowButtonGridData.widthHint = 23;

	prevButton = new Button(buttons, SWT.ARROW | SWT.LEFT);
	prevButton.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "Previous");
	prevButton.setLayoutData(arrowButtonGridData);

	nextButton = new Button(buttons, SWT.ARROW | SWT.RIGHT);
	nextButton.setData(Utility.ATOSJ_COMPONENT_NAME_KEY, "Next");
	nextButton.setLayoutData(arrowButtonGridData);
    }

    /**
     * Creates an instance of this class, sets the input and finally opens it.
     * 
     * @param parent
     *                the parent shell to which this window belongs
     * @param input
     *                the data object to be displayed in the window
     * @param caller
     *                the {@link ForeignKeyConstraintSelector} instance which
     *                calls the constructor.
     */
    public CompanyWindow(Shell parent, Company input,
	    final ForeignKeyConstraintSelector caller) {
	this(parent);

	createButtonListener(caller);

	setInput(input);

	shell.open();
    }

    /**
     * Loads a given client record into the window form of initialize the
     * elements of the form the empty string/null if no data is given.
     * 
     * @param company
     *                object which contains the data to be displayed or
     *                <tt>null</tt> if a completely new record is to be
     *                edited.
     */
    private void setInput(Company company) {
	/* STEP 1: switch off the listeners */
	settingInput = true;

	/* STEP 2: unlock the actually displayed data record (if exists) */
	if (this.input != null && inputEditingEnabled)
	    Company.lockedIds.remove(new Integer(this.input.getId()));

	/*
	 * STEP 3: loading the given (new) data instance into the window form
	 * (if not null else initialize the elements)
	 */
	if (company != null) {
	    numberLabel.setEnabled(true);
	    numberText.setText(new Integer(company.getId()).toString());
	    shortNameText.setFocus();

	    if (company.getShortName() != null)
		shortNameText.setText(company.getShortName());
	    else
		shortNameText.setText("");
	    if (company.getSalutation() != null)
		salutationCombo.setText(company.getSalutation());
	    else
		salutationCombo.setText("");
	    if (company.getTitle() != null)
		titleCombo.setText(company.getTitle());
	    else
		titleCombo.setText("");
	    if (company.getFirstname() != null)
		firstNameText.setText(company.getFirstname());
	    else
		firstNameText.setText("");
	    if (company.getName() != null)
		nameText.setText(company.getName());
	    else
		nameText.setText("");
	    if (company.getStreet() != null)
		streetText.setText(company.getStreet());
	    else
		streetText.setText("");
	    if (company.getZipCode() != null)
		zipCodeText.setText(company.getZipCode());
	    else
		zipCodeText.setText("");
	    if (company.getCity() != null)
		cityText.setText(company.getCity());
	    else
		cityText.setText("");
	    if (company.getCountry() != null)
		countryCombo.setText(company.getCountry());
	    else
		countryCombo.setText("");
	    if (company.getAnnex() != null)
		annexCombo.setText(company.getAnnex());
	    else
		annexCombo.setText("");
	    if (company.getPhone() != null)
		phoneText.setText(company.getPhone());
	    else
		phoneText.setText("");
	    if (company.getMobile() != null)
		mobileText.setText(company.getMobile());
	    else
		mobileText.setText("");
	    if (company.getFax() != null)
		faxText.setText(company.getFax());
	    else
		faxText.setText("");
	    if (company.getEmail() != null)
		emailText.setText(company.getEmail());
	    else
		emailText.setText("");
	    if (company.getCpSalutation() != null)
		cpSalutationCombo.setText(company.getCpSalutation());
	    else
		cpSalutationCombo.setText("");
	    if (company.getCpTitle() != null)
		cpTitleCombo.setText(company.getCpTitle());
	    else
		cpTitleCombo.setText("");
	    if (company.getCpFirstname() != null)
		cpFirstNameText.setText(company.getCpFirstname());
	    else
		cpFirstNameText.setText("");
	    if (company.getCpName() != null)
		cpNameText.setText(company.getCpName());
	    else
		cpNameText.setText("");
	    if (company.getCpPhone() != null)
		cpPhoneText.setText(company.getCpPhone());
	    else
		cpPhoneText.setText("");
	    if (company.getCpMobile() != null)
		cpMobileText.setText(company.getCpMobile());
	    else
		cpMobileText.setText("");
	    if (company.getCpFax() != null)
		cpFaxText.setText(company.getCpFax());
	    else
		cpFaxText.setText("");
	    if (company.getCpEmail() != null)
		cpEmailText.setText(company.getCpEmail());
	    else
		cpEmailText.setText("");
	    if (company.getCpSalutation() != null)
		cpSalutationCombo.setText(company.getCpSalutation());
	    else
		cpSalutationCombo.setText("");
	    if (company.getCpDepartment() != null)
		cpDepartmentText.setText(company.getCpDepartment());
	    else
		cpDepartmentText.setText("");
	    if (company.getCpTask() != null)
		cpTaskText.setText(company.getCpTask());
	    else
		cpTaskText.setText("");

	    customerSinceCalendar.setDate(company.getCustomerSince());
	    cpBirthDayCalendar.setDate(company.getCpBirthDay());

	    if (company.getTurnover() != null)
		turnoverText.setText(Utility.createFloatText(company
			.getTurnover()));
	    else
		turnoverText.setText("");

	    if (company.getShortInfo() != null)
		shortMessageText.setText(company.getShortInfo());
	    else
		shortMessageText.setText("");
	    if (company.getNotices() != null)
		memoText.setText(company.getNotices());
	    else
		memoText.setText("");
	    try {
		employeeControl.setInput(company.getId());
		bookingsControl.setInput(company.getId());
	    } catch (SQLException e) {/* TODO */
	    }

	} else {
	    // no data given (client == null): initialize elements
	    numberLabel.setEnabled(false);
	    shortNameText.setFocus();
	    shortNameText.setText("");
	    numberText.setText("");
	    salutationCombo.setText("");
	    titleCombo.setText("");
	    firstNameText.setText("");
	    nameText.setText("");
	    streetText.setText("");
	    zipCodeText.setText("");
	    cityText.setText("");
	    countryCombo.setText("");
	    annexCombo.setText("");
	    phoneText.setText("");
	    mobileText.setText("");
	    faxText.setText("");
	    emailText.setText("");

	    cpSalutationCombo.setText("");
	    cpTitleCombo.setText("");
	    cpFirstNameText.setText("");
	    cpNameText.setText("");
	    cpPhoneText.setText("");
	    cpMobileText.setText("");
	    cpFaxText.setText("");
	    cpEmailText.setText("");
	    cpDepartmentText.setText("");
	    cpTaskText.setText("");

	    customerSinceCalendar.setDate(null);
	    cpBirthDayCalendar.setDate(null);

	    turnoverText.setText("");
	    shortMessageText.setText("");
	    memoText.setText("");
	    try {
		employeeControl.setInput(AbstractTable.NULL_ID);
		bookingsControl.setInput(AbstractTable.NULL_ID);
	    } catch (SQLException e) {/* TODO */
	    }
	}

	/*
	 * STEP 4: Check if the given record is already locked, i.e. it is
	 * already edited (if data object is not null, else enable the
	 * elements). -> yes: disable the form elements -> no: enable them and
	 * lock the new record
	 */
	if (company != null) {
	    boolean alreadyEditing = Company.lockedIds.contains(new Integer(
		    company.getId()));
	    setInputComponentsEnabled(!alreadyEditing);

	    if (!alreadyEditing) {
		Company.lockedIds.add(new Integer(company.getId()));
	    }
	}
	// completely new data record
	else
	    setInputComponentsEnabled(true);

	/*
	 * STEP 5: set input to the new data object, inputChanged to true and
	 * enable next/prev buttons
	 */
	this.input = company;
	inputChanged = (company == null);

	prevButton.setEnabled(this.input != null);
	nextButton.setEnabled(this.input != null);

	/* STEP 6: set the window title */
	String shellText;
	if (input == null)
	    shellText = Messages.getString("GUIText.NewItemWindowTitleText");
	else
	    shellText = input.getId() + ", " + input.getSalutation() + ", "
		    + input.getName() + ", ";

	shellText += Messages.getString("GUIText.CompanyWindowTitleText");
	if (input == null)
	    shellText += "*";
	shell.setText(shellText);

	/* STEP 7: switch on the listeners */
	settingInput = false;
    }

    /**
     * According to the value of the given parameter (<tt>true</tt>/<tt>false</tt>)
     * this method enables / disables the widgets of the window form.<br>
     * <br>
     * 
     * <i>Note:</i> It also sets the member {@link #inputEditingEnabled} to the
     * value of the parameter to signal that editing of the input has been
     * enabled or not.
     * 
     * @param enabled
     *                if equals <tt>true</tt> the widgets are enabled
     *                otherwise the widgets get disabled.
     */
    private void setInputComponentsEnabled(boolean enabled) {
	numberText.setEnabled(enabled);
	shortNameText.setEnabled(enabled);
	salutationCombo.setEnabled(enabled);
	titleCombo.setEnabled(enabled);
	firstNameText.setEnabled(enabled);
	nameText.setEnabled(enabled);
	streetText.setEnabled(enabled);
	zipCodeText.setEnabled(enabled);
	cityText.setEnabled(enabled);
	countryCombo.setEnabled(enabled);
	annexCombo.setEnabled(enabled);
	phoneText.setEnabled(enabled);
	mobileText.setEnabled(enabled);
	faxText.setEnabled(enabled);
	emailText.setEnabled(enabled);

	cpSalutationCombo.setEnabled(enabled);
	cpTitleCombo.setEnabled(enabled);
	cpFirstNameText.setEnabled(enabled);
	cpNameText.setEnabled(enabled);
	cpPhoneText.setEnabled(enabled);
	cpMobileText.setEnabled(enabled);
	cpFaxText.setEnabled(enabled);
	cpEmailText.setEnabled(enabled);
	cpDepartmentText.setEnabled(enabled);
	cpBirthDayCalendar.setEnabled(enabled);
	cpTaskText.setEnabled(enabled);

	turnoverText.setEnabled(enabled);
	customerSinceCalendar.setEnabled(enabled);

	shortMessageText.setEnabled(enabled);
	memoText.setEnabled(enabled);
	employeeControl.setEnabled(enabled);
	bookingsControl.setEnabled(enabled);

	okButton.setEnabled(enabled);
	applyButton.setEnabled(enabled);
	newButton.setEnabled(enabled);
	abortButton.setEnabled(enabled);
	prevButton.setEnabled(enabled);
	nextButton.setEnabled(enabled);

	inputEditingEnabled = enabled;

    }

    /**
     * Adds a listener to several buttons of the window form.<br>
     * <br>
     * 
     * This involves at the moment the buttons {@link #okButton},
     * {@link #abortButton}, {@link #applyButton}, {@link #newButton},
     * {@link #prevButton}, {@link #nextButton}.
     * 
     * @param caller
     *                {@link ForeignKeyConstraintSelector} instance which called
     *                the constructor which itself calls this method.
     */
    private void createButtonListener(final ForeignKeyConstraintSelector caller) {

	if (caller == null) { // normal mode, no caller
	    okButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
		    if (onSave())
			shell.close();
		}
	    });

	    applyButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event arg0) {
		    onSave();
		}
	    });
	} else {// caller mode
	    okButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event event) {
		    if (onSave()) {
			caller.setSelectedId(input.getId());
			shell.close();
		    }

		}
	    });

	    applyButton.addListener(SWT.Selection, new Listener() {
		public void handleEvent(Event arg0) {
		    if (onSave()) {
			caller.setSelectedId(input.getId());
		    }
		}
	    });
	}

	newButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (onSave())
		    setInput(null);
	    }
	});

	abortButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		shell.close();
	    }
	});

	prevButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (inputChanged) {
		    if (confirmClose())
			setInput(Company.getPrevious(input.getId()));
		} else
		    setInput(Company.getPrevious(input.getId()));
	    }
	});

	nextButton.addListener(SWT.Selection, new Listener() {
	    public void handleEvent(Event arg0) {
		if (inputChanged) {
		    if (confirmClose())
			setInput(Company.getNext(input.getId()));
		} else
		    setInput(Company.getNext(input.getId()));
	    }
	});
    }

    /**
     * Checks if all obligatory attributes of a {@link Company} record are
     * entered into the window form and if the entered fees are correct float
     * numbers.
     * 
     * @return <tt>true</tt> if all mandatory fields are set and the fee
     *         values are valid float numbers (if entered), otherwise
     *         <tt>false</tt>.
     * 
     * @see semorg.sql.util.Utility#isCorrectFloat(String)
     */
    protected boolean checkInput() {
	boolean inputOK = true;
	String errorMessage = "";
	if (shortNameText.getText().trim().length() == 0) {
	    errorMessage += "";
	    inputOK = false;
	}
	if (salutationCombo.getText().trim().length() == 0) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogMandatoryFieldSalutationText");
	    inputOK = false;
	}
	if (nameText.getText().trim().length() == 0) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogMandatoryFieldLastNameText");
	    inputOK = false;
	}
	if (cpSalutationCombo.getText().trim().length() == 0) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogMandatoryFieldCpSalutationText");
	    inputOK = false;
	}
	if (cpNameText.getText().trim().length() == 0) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogMandatoryFieldLastNameText");

	    inputOK = false;
	}
	if (!Utility.isCorrectFloat(turnoverText.getText())) {
	    errorMessage += Messages
		    .getString("GUIText.ErrorMessageDialogIncorrectFloatTurnOverText");
	    inputOK = false;
	}

	if (!inputOK) {
	    MessageDialog
		    .openInformation(
			    shell,
			    Messages
				    .getString("GUIText.ErrorMessageDialogMandatoryFieldWindowTitle"),
			    errorMessage);
	}

	return inputOK;
    }

    /**
     * Reads the data from the window form elements, sets the values to a
     * {@link Company} instance and commits the changes / the new record into
     * the database.
     * 
     * Furthermore the member {@link #input} is set to the new values.
     * 
     */
    protected void commitInputToDB() {

	if (input == null) {
	    // new record into the db
	    Company newInput = new Company(Company.NULL_ID, shortNameText
		    .getText(), salutationCombo.getText(),
		    titleCombo.getText(), firstNameText.getText(), nameText
			    .getText(), streetText.getText(), zipCodeText
			    .getText(), cityText.getText(), countryCombo
			    .getText(), annexCombo.getText(), phoneText
			    .getText(), mobileText.getText(),
		    faxText.getText(), emailText.getText(), cpSalutationCombo
			    .getText(), cpTitleCombo.getText(), cpFirstNameText
			    .getText(), cpNameText.getText(), cpPhoneText
			    .getText(), cpMobileText.getText(), cpFaxText
			    .getText(), cpEmailText.getText(), cpDepartmentText
			    .getText(),

		    cpBirthDayCalendar.getDate(),

		    cpTaskText.getText(), shortMessageText.getText(), memoText
			    .getText(), Utility.parseFloat(turnoverText
			    .getText()),

		    customerSinceCalendar.getDate(),

		    new Timestamp(System.currentTimeMillis()), new Timestamp(
			    System.currentTimeMillis()));
	    input = newInput;
	    try {
		int id = input.insertIntoDB();
		numberText.setText(new Integer(id).toString());
	    } catch (SQLException e) {
		e.printStackTrace();
	    }
	} else {
	    // update an existing record
	    input.setShortName(shortNameText.getText());

	    input.setSalutation(salutationCombo.getText());
	    input.setTitle(titleCombo.getText());
	    input.setFirstname(firstNameText.getText());
	    input.setName(nameText.getText());

	    input.setStreet(streetText.getText());
	    input.setZipCode(zipCodeText.getText());
	    input.setCity(cityText.getText());
	    input.setCountry(countryCombo.getText());
	    input.setAnnex(annexCombo.getText());

	    input.setPhone(phoneText.getText());
	    input.setMobile(mobileText.getText());
	    input.setFax(faxText.getText());
	    input.setEmail(emailText.getText());

	    input.setCpSalutation(cpSalutationCombo.getText());
	    input.setCpTitle(cpTitleCombo.getText());
	    input.setCpFirstname(cpFirstNameText.getText());
	    input.setCpName(cpNameText.getText());

	    input.setCpPhone(cpPhoneText.getText());
	    input.setCpMobile(cpMobileText.getText());
	    input.setCpFax(cpFaxText.getText());
	    input.setCpEmail(cpEmailText.getText());

	    input.setCpDepartment(cpDepartmentText.getText());
	    input.setCpBirthDay(cpBirthDayCalendar.getDate());
	    input.setCpTask(cpTaskText.getText());

	    input.setShortInfo(shortMessageText.getText());
	    input.setNotices(memoText.getText());

	    input.setTurnover(Utility.parseFloat(turnoverText.getText()));
	    input.setCustomerSince(customerSinceCalendar.getDate());

	    try {
		input.updateDB();
	    } catch (SQLException e) {
		e.printStackTrace();
	    }
	}

	try {
	    employeeControl.commitIntoDB(input.getId());
	} catch (SQLException e) {
	    e.printStackTrace();
	}

	try {
	    bookingsControl.commitIntoDB(input.getId());
	} catch (SQLException e) {
	    e.printStackTrace();
	}

	CompanyListWindow.instance.update();
    }

    /**
     * Creates a message dialog if the data in the window form has been changed
     * (or was entered newly) and these changes haven't been confirmed (e.g. by
     * clicking the ok button) or discarded so far. It also receives the
     * decision of the user (confirm/discard changes or abort the window
     * closing) and handels it.
     * 
     * In the positive case (confirmation of the changes) it invokes the method
     * {@link #onSave()}.
     * 
     * @return <tt>true</tt> if the shell can be closed and <tt>false</tt>
     *         otherwise.
     */
    private boolean confirmClose() {

	MessageDialog dlg;

	if (input == null) {
	    dlg = new MessageDialog(
		    shell,
		    Messages
			    .getString("GUIText.SaveNewItemMessageDialogWindowTitle"),
		    null,
		    Messages
			    .getString("GUIText.SaveNewItemMessageDialogQuestionText"),
		    MessageDialog.QUESTION,
		    new String[] {
			    Messages
				    .getString("GUIText.SaveNewItemMessageDialogYesButtonText"),
			    Messages
				    .getString("GUIText.SaveNewItemMessageDialogNoButtonText"),
			    Messages
				    .getString("GUIText.SaveNewItemMessageDialogAbortButtonText") },
		    0);
	} else {
	    dlg = new MessageDialog(
		    shell,
		    Messages
			    .getString("GUIText.SaveChangesMessageDialogWindowTitle"),
		    null,
		    Messages
			    .getString("GUIText.SaveChangesMessageDialogQuestionText"),
		    MessageDialog.QUESTION,
		    new String[] {
			    Messages
				    .getString("GUIText.SaveChangesMessageDialogYesButtonText"),
			    Messages
				    .getString("GUIText.SaveChangesMessageDialogNoButtonText"),
			    Messages
				    .getString("GUIText.SaveChangesMessageDialogAbortButtonText") },
		    0);
	}
	switch (dlg.open()) {
	case 0:
	    return onSave();
	case 1:
	    return true;
	case 2:
	    return false;
	default:
	    return true;
	}
    }

    /**
     * Checks whether the input has been changed (i.e. inputChanged equals
     * <tt>true</tt>) or not. If changes have been done, it firstly checks if
     * the changes are valid ({@link #checkInput()}), secondly invokes the
     * method {@link #commitInputToDB()} to commit the changes and thirdly
     * updates the GUI by invoking the method {@link #setInput(Company)}.
     * 
     * @return <tt>true</tt> if nothing has changed or the commit of the
     *         changes to the database was successful, <tt>false</tt>
     *         otherwise.
     */
    private boolean onSave() {
	if (!inputChanged)
	    return true;
	if (checkInput()) {
	    commitInputToDB();
	    setInput(input);
	    return true;
	} else
	    return false;
    }
}
