/*
 * MiningMart Version 1.0
 * 
 * Copyright (C) 2006 Martin Scholz, Timm Euler, 
 *                    Daniel Hakenjos, Katharina Morik
 *
 * Contact: miningmart@ls8.cs.uni-dortmund.de
 *
 * A list of contributing developers (other than the copyright 
 * holders) can be found at
 * http://mmart.cs.uni-dortmund.de/downloads/download.html
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program, see the file MM_HOME/LICENSE; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 */
package edu.udo.cs.miningmart.gui.application;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import org.jhotdraw.figures.LineConnection;
import org.jhotdraw.framework.Drawing;
import org.jhotdraw.framework.DrawingView;
import org.jhotdraw.framework.Figure;
import org.jhotdraw.framework.FigureEnumeration;
import org.jhotdraw.util.Iconkit;
import org.musoft.limo.application.Application;
import org.musoft.limo.application.MenuBar;
import org.musoft.limo.application.Resource;
import org.musoft.limo.application.ToolBar;
import org.musoft.limo.drawing.DrawingPanel;
import org.musoft.limo.drawing.ModelConnection;
import org.musoft.limo.drawing.ModelDrawing;
import org.musoft.limo.drawing.ModelFigure;
import org.musoft.limo.model.Model;
import org.musoft.limo.model.ModelConnectionElement;
import org.musoft.limo.model.ModelFigureElement;
import org.musoft.limo.util.Preferences;

import edu.udo.cs.miningmart.compiler.CompilerAccess;
import edu.udo.cs.miningmart.compiler.CompilerAccessLogic;
import edu.udo.cs.miningmart.compiler.M4CompilerInterfaceError;
import edu.udo.cs.miningmart.db.ConfigReader;
import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.gui.concepteditor.ConceptPanel;
import edu.udo.cs.miningmart.gui.model.MiningMartCase;
import edu.udo.cs.miningmart.gui.model.MiningMartChain;
import edu.udo.cs.miningmart.gui.model.MiningMartConcept;
import edu.udo.cs.miningmart.gui.model.MiningMartConcepts;
import edu.udo.cs.miningmart.gui.model.MiningMartModel;
import edu.udo.cs.miningmart.gui.model.MiningMartModelFigureElement;
import edu.udo.cs.miningmart.gui.model.MiningMartStep;
import edu.udo.cs.miningmart.gui.stepsettings.StepSettingsPanel;
import edu.udo.cs.miningmart.gui.util.CaseExporter;
import edu.udo.cs.miningmart.gui.util.CaseImporter;
import edu.udo.cs.miningmart.gui.util.CaseTrasher;
import edu.udo.cs.miningmart.gui.util.DbConfigEditor;
import edu.udo.cs.miningmart.gui.util.GarbageCollector;
import edu.udo.cs.miningmart.installer.MmInstallerTools;
import edu.udo.cs.miningmart.m4.Case;
import edu.udo.cs.miningmart.m4.Chain;
import edu.udo.cs.miningmart.m4.Concept;
import edu.udo.cs.miningmart.m4.M4Interface;
import edu.udo.cs.miningmart.m4.Step;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 * The MiningMartApplication.
 * @author Daniel Hakenjos
 * @version $Id: MiningMartApplication.java,v 1.19 2006/04/11 14:10:15 euler Exp $
 */
public class MiningMartApplication extends Application {

	private Drawing drawing;

	public static final String SYSTEM_PROP_MM_HOME = "MM_HOME";
	
	public static boolean compileLazy = true;
//	public static Level verbosity = Print.DEFAULT_VERBOSITY;
	public static CompilerThread compilerThread;
	public static CompilerAccess compilerAccess = null;

	// bit of a hack to avoid releasing the case when switching
	// from case to concept editor:
	public static boolean keepCase = false;
	
	public static M4Interface m4Interface;
	private static CaseExporter caseExporter;
	private static CaseImporter caseImporter;
	private static CaseTrasher caseTrasher;

	public Case currentcase;
	private String opsintoolpanel;
	//operator in toolpanel as Vector;
	private Vector opsintp_vector;

	private OperatorToolPanel operatortoolpanel;
	private ConceptToolPanel concepttoolpanel;
	
	private ConceptPanel conceptpanel;

	private StepSettingsPanel stepsettings;

	private boolean showstepsettings = false;

	public PrintViewer logservice;

	private String actualcasename = null;

	private String workingdir;
	
	private int nrFeatures;
	
	private boolean drawSubconceptLinks = true;
	private boolean drawRelationships = true;
	private boolean drawProjections = true;

	private Point operatorPoint, conceptPoint;

	private Collection datamodel;
	
//	private edu.udo.cs.miningmart.gui.concepteditor.ConceptEditor concepteditor;
	
	private int 				editormode			= DEFAULT_MODE;
	
	public static int 		DEFAULT_MODE 	= 0;
	
	public static final int	CASE_MODE 		= 0;

	public static final int	CONCEPT_MODE	= 1;

	boolean openedCaseEditor,openedForUpdate;

	/**
	 * Creates new <code>MiningMartApplication</code>.
	 */
	public MiningMartApplication() {
		super();
		Iconkit kit = new Iconkit(this);

		this.setIconImage(
			kit.loadImageResource(Resource.getString("MMART_ICON")));

		m4Interface = M4Interface.getInstance();

		logservice = new PrintViewer(this);
		showComponentInTab(logservice,Application.PANE_CENTER,false);
		
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		((MiningMartMenuBar) getJMenuBar()).setRecentCasesGUI();
	}
	
	/**
	 * Gets the editor mode.
	 */
	public int getEditorMode(){
		return editormode;
	}

	/**
	 * Sets the editor mode.
	 * @param mode 
	 * @see CASE_MODE
	 * @see CONCEPT_MODE 
	 */	
	public void setEditorMode(int mode){
		if (editormode==mode)
			return;
		editormode=mode;
		((MiningMartMenuBar) getJMenuBar()).promptSwitchEditor();
	}

	/* (non-Javadoc)
	 * @see org.musoft.limo.application.Application#createComponents()
	 */
	protected void createComponents() {
		super.createComponents();
//		this.concepteditor=new edu.udo.cs.miningmart.gui.concepteditor.ConceptEditor(this);
	}

	/**
	 * @see org.musoft.limo.application.Application#createModel()
	 */
	protected Model createModel() {
		if (currentcase == null) {
			currentcase = M4Interface.getCurrentCase();
		}
		if (currentcase == null) {
			return null;
		}

		if (editormode==CASE_MODE){
			MiningMartCase mmcase = new MiningMartCase(this, currentcase);
			mmcase.initTheCase();
			return mmcase;
		}
		if (editormode==CONCEPT_MODE){
			MiningMartConcepts mmartconcepts = new MiningMartConcepts(this);
			mmartconcepts.initConcepts();

			return mmartconcepts;
		}

		return null;
	}
	
	/**
	 * Gets the MiningMartCase.
	 */	
	public MiningMartCase getMiningMartCase(){
		if (getEditorMode()==CASE_MODE){
			return (MiningMartCase) getModel();
		}
		return null;
	}
	
	/**
	 * Gets the MiningMartConcepts.
	 */	
	public MiningMartConcepts getMiningMartConcepts(){
		if (getEditorMode()==CONCEPT_MODE){
			return (MiningMartConcepts) getModel();
		}
		return null;
	}

	/**
	 * @see org.musoft.limo.application.Application#createToolBar()
	 */
	protected ToolBar createToolBar() {
		return new MiningMartToolBar(this);
	}

	/**
	 * @see org.musoft.limo.application.Application#createMenuBar()
	 */
	protected MenuBar createMenuBar() {
		return new MiningMartMenuBar(this);
	}

	/**
	 * Creates the drawing used in this application.
	 * You need to override this method to use a Drawing
	 * subclass in your application. By default a standard
	 * Drawing is returned.
	 * @see org.musoft.limo.application.Application#createDrawing(Model)
	 */
	protected Drawing createDrawing(Model rootElement) {
		if (rootElement instanceof MiningMartCase) {
			drawing = new MiningMartDrawing(this, (MiningMartCase) rootElement);
		}
		if (rootElement instanceof MiningMartChain) {
			drawing =
				new MiningMartDrawing(this, (MiningMartChain) rootElement);
		}
		if (rootElement instanceof MiningMartConcepts) {
			drawing =
				new MiningMartDrawing(this, (MiningMartConcepts) rootElement);
		}
		return drawing;
	}

	/**
	 * @see org.musoft.limo.application.Application#createDrawingView(Model)
	 */
	protected DrawingView createDrawingView(Model rootElement) {
		boolean wasDirty = currentModel.getDirty();
		MiningMartDrawingView mmartdrawview = new MiningMartDrawingView(this);

		mmartdrawview.setDrawing(createDrawing(rootElement));

		mmartdrawview.addMiningMartSelectionListener(
			new MiningMartSelectionListener(this));
	

		fireViewCreatedEvent(mmartdrawview);

		currentModel.setDirty(wasDirty);

		return mmartdrawview;

	}

	/**
	 * Gets the <code>Drawing</code>.
	 */
	public Drawing getDrawing() {
		return drawing;
	}

	/**
	 * @see org.musoft.limo.application.Application#getModelClassPrefix()
	 */
	protected String[] getModelClassPrefix() {
		return new String[] { "miningmart.hci.gui.model." };
	}

	/**
	 * @see CH.ifa.draw.framework.FigureSelectionListener#figureSelectionChanged(DrawingView)
	 */
	public void figureSelectionChanged(DrawingView dw) {
		super.figureSelectionChanged(dw);

		try {
			FigureEnumeration fenum = dw.selection();
			while (fenum.hasNextFigure()) {
				Figure fig = fenum.nextFigure();
				if (fig instanceof ModelFigure) {
					ModelFigure mofig = (ModelFigure) fig;
					if (dw.isFigureSelected(mofig)) {
						mofig.bringToFront();
					}
				} else if (fig instanceof ModelConnection) {
					ModelConnection mocon = (ModelConnection) fig;
					if (dw.isFigureSelected(mocon)) {
						mocon.bringToFront();
					}
				}
			}
		} catch (Exception e) {
			M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
		}
	}

	/**
	 * @see org.musoft.limo.application.Application#getApplicationName()
	 */
	public String getApplicationName() {
		return Resource.getString("APP_TITLE");
	}

	/**
	* Legt die initiale Groessee der Applikation und die Komponenten fest, mit der das Layout der Applikation initialisiert wird, kann von
	* konkreten Anwendungen ueberschrieben werden.
	*/
	protected void setDefaultLayout() {
		// die minimale Groesse festlegen
		Dimension d = new Dimension(800, 600);
		if (getWidth() < d.width) {
			setSize(d.width, d.height);
		}
	}

	/**
	 * Sets the system-properties.
	 */
	public static void setSystemProperties() {
		// set defaults:
		setDefaultProperties();
	}

	public static void setDefaultProperties() {
		String home = System.getProperty(MiningMartApplication.SYSTEM_PROP_MM_HOME);
		System.setProperty(M4Interface.SYSTEM_PROP_PRINT_VERBOSITY, "Operator");
		System.setProperty("TEMP_DIR", home + File.separator + "temp" + File.separator);
		System.setProperty("LOG_FILES", home + File.separator + "log" + File.separator);
		System.setProperty("ML_HOME", home + File.separator + "ext" + File.separator);		
	}
	
	/** Returns an ImageIcon, or null if the path was invalid. */
	protected static ImageIcon createImageIcon(
		String path,
		String description) {
		java.net.URL imgURL = MiningMartApplication.class.getResource(path);
		//System.out.println(imgURL.toString());
		if (imgURL != null) {
			return new ImageIcon(imgURL, description);
		} else {
			M4Interface.print.doPrint(Print.ERROR,"Couldn't find file: " + path);
			return null;
		}
	}

	/**
	 * Gets the point for a new operator.
	 */
	public Point getPointforOperator() {
		if (operatorPoint != null)
			return operatorPoint;
		return new Point(10, 10);
	}
	
	/**
	 * Sets the point for a new operator.
	 */
	public void setPointForOperator(Point point) {
		this.operatorPoint = point;
	}
	
	/**
	 * Gets the point for a new concept.
	 */
	public Point getPointforConcept(){
		if (conceptPoint != null)
			return conceptPoint;
		return new Point(10, 10);
	}


	/**
	 * Sets the point for a new concept.
	 */
	public void setPointForConcept(Point point) {
		this.conceptPoint = point;
	}

	/**
	 * Gets the potential parent for the specified coordinate.
	 */
	public ModelFigureElement getPotentialParent(int x, int y) {
		JPanel panel = getMainPane().getCurrentPanel();
		if (panel instanceof DrawingPanel) {
			return ((ModelDrawing) ((DrawingPanel) panel).getDrawing())
				.getModel();
		}
		return null;
	}

	/**
	 * @see org.musoft.limo.application.Application#showHelp()
	 */
	public void showHelp() {
		((MiningMartMenuBar) this.getJMenuBar()).show_help.setSelected(true);
		super.showHelp();
	}

	/**
	 * Removes the help.
	 */
	public void removeHelp() {
		((MiningMartMenuBar) this.getJMenuBar()).show_help.setSelected(false);
		removeComponentFromTab(help);
	}

	/**
	 * @see org.musoft.limo.application.Application#showAboutDialog()
	 */
	public void showAboutDialog() {
		AboutDialog aboutDialog = new AboutDialog(this);
	}

	// Compiler
	public CompilerAccess getCompilerAccess() {
		if (compilerAccess == null) {
			return new CompilerAccessLogic(M4Interface.getInstance().getM4db(), M4Interface.print);
		}
		return compilerAccess;
	}

	/**
	 * @see org.musoft.limo.application.Application#saveParams()
	 */
	public void saveParams() {
		super.saveParams();

		Preferences pref = this.getPreferences();
		opsintoolpanel = new String("");
		for (int i = 0; i < opsintp_vector.size(); i++) {
			opsintoolpanel += (String) opsintp_vector.get(i);
			if ((i + 1) < opsintp_vector.size()) {
				opsintoolpanel += ";";
			}
		}
		pref.putString("OperatorToolPanel", opsintoolpanel);

		String rec_cases =
			((MiningMartMenuBar) this.getJMenuBar())
				.getRecentCases()
				.toString();
		pref.putString("RecentCases", rec_cases);

		pref.putString("WorkingDir", workingdir);
		pref.putInt("NumberFeatures",nrFeatures);


		pref.putString("Verbosity", M4Interface.print.getMinimumVerbosityLevel().getName());

		String lazy = "false";
		if (compileLazy)
			lazy = "true";
		pref.putString("CompileLazy", lazy);

		pref.putString("openedCaseEditor",openedCaseEditor?"true":"false");
		pref.putString("openedForUpdate",openedForUpdate?"true":"false");


/*		pref.save(getUserHome()+ File.separatorChar+".mmart"
			+ File.separatorChar
			+ getApplicationName() + ".cfg");*/
		pref.save(System.getProperty(MiningMartApplication.SYSTEM_PROP_MM_HOME)+ File.separatorChar+"config"
			+ File.separatorChar
			+ getApplicationName() + ".cfg");
	}

	/**
	 * @see org.musoft.limo.application.Application#loadParams()
	 */
	public void loadParams() {
		super.loadParams();

		/*Preferences pref = new Preferences( getUserHome()+ File.separatorChar+".mmart" + File.separatorChar
																+ getApplicationName() + ".cfg");*/
		Preferences pref = new Preferences( System.getProperty(MiningMartApplication.SYSTEM_PROP_MM_HOME)+ File.separatorChar+"config" + File.separatorChar
																+ getApplicationName() + ".cfg");

		String ops = pref.getString("OperatorToolPanel");
		opsintp_vector = new Vector();
		if (ops != null) {
			StringTokenizer st = new StringTokenizer(ops, ";");
			while (st.hasMoreTokens()) {
				opsintp_vector.add(st.nextToken());
			}
		}

		workingdir = pref.getString("WorkingDir", System.getProperty("user.home"));
		nrFeatures=pref.getInt("NumberFeatures",10);

		String givenVerbosity = System.getProperty("PRINT_VERBOSITY");
		if (givenVerbosity == null) {
			givenVerbosity = Print.DEFAULT_VERBOSITY.getName();
		}
		
		Level verbosity = Print.getVerbosityLevelForName(pref.getString("Verbosity", givenVerbosity));
		//Level verbosity = Print.getVerbosityLevelForName(givenVerbosity);
		M4Interface.print.setMinimumVerbosityLevel(verbosity);

		String lazy = pref.getString("CompileLazy", "true");
		if (lazy.equals("true")) {
			compileLazy = true;
		} else {
			compileLazy = false;
		}
		
		openedCaseEditor=pref.getString("openedCaseEditor","true").equals("true")?true:false;
		openedForUpdate=pref.getString("openedForUpdate","true").equals("true")?true:false;
	}

	/**
	 * Gets the working directory.
	 */
	public String getWorkingDir() {
		return workingdir;
	}

	/**
	 * Sets the working directorty.
	 */
	public void setWorkingDir(String dir) {
		workingdir = dir;
	}

	/**
	 * Gets the operators in the toolpanel.
	 */
	public Vector getOperatorsInToolPanel() {
		return opsintp_vector;
	}

	/**
	 * Sets the operator in the toolpanel.
	 */
	public void setOperatorInToolPanel(Vector vector) {
		this.opsintp_vector = (Vector) vector.clone();
	}

	/**
	 * Refreshs the operatortoolpanel.
	 */
	public void refreshOperatorToolPanel() {
		if (getEditorMode()==CONCEPT_MODE){
			return;
		}
		if (currentcase != null)
			this.removeComponentFromTab(operatortoolpanel.getOperatorToolPanel());
		operatortoolpanel = new OperatorToolPanel(this);
		if (currentcase != null)
			showComponentInTab(operatortoolpanel.getOperatorToolPanel(),Application.PANE_RIGHT,	false);
	}
/*
	 * Adds the <code>ConceptEditor</code> to the left top pane.
	public void addConceptEditor() {
		//init the concept editor
		conceptEditor = new ConceptEditor();
		conceptEditor.setInterface(m4Interface);
		try {
			conceptEditor.init();
		} catch (M4Exception e) {
			M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
		}
		JTree tree = conceptEditor.getConceptTree();
		conceptPanel = new JPanel() {
			public String toString() {
				return Resource.getString("CONCEPTEDITOR_PANEL_TREE");
			}
		};
		conceptPanel.setLayout(new BorderLayout());
		conceptPanel.add(new JScrollPane(tree), BorderLayout.CENTER);

		showComponentInTab(conceptPanel, Application.PANE_LEFT_TOP, false);
//		showComponentInTab(concepteditor,Application.PANE_LEFT_TOP, false);
	}

	 * Removes the <code>ConceptEditor</code>.
	public void removeConceptEditor() {
		if (conceptPanel != null)
			this.removeComponentFromTab(conceptPanel);
	}

	 * Shows the <code>ConceptEditor</code>.
	public void showConceptEditor() {
		if (conceptPanel != null)
			this.selectComponentInTab(conceptPanel);
	}*/

	public void promptOpen() {
		promptOpen(null, true);
	}

	public void promptOpen(String casename, boolean openCaseForUpdating) {
		if (currentcase != null){
			if (!promptClose()){
				return;
			}
		}
		int exitaction = OpenCaseDialog.SELECT;

//this.setEditorMode(CASE_MODE);
		if (casename == null) {
			OpenCaseDialog opencased = new OpenCaseDialog(this);
			exitaction = opencased.getExitAction();
			if (exitaction == OpenCaseDialog.SELECT) {
				casename = opencased.getSelectedCase();
				openCaseForUpdating = opencased.openCaseForUpdating();
				if (opencased.openCaseEditor()){
					this.setEditorMode(CASE_MODE);
				}else{
					this.setEditorMode(CONCEPT_MODE);
				}
			}
		}

		if (exitaction == OpenCaseDialog.SELECT) {
			OpenCaseThread openthread =
				new OpenCaseThread(this, casename, openCaseForUpdating, ( ! MiningMartApplication.keepCase));

			OpeningCaseDialog dialog =
				new OpeningCaseDialog(this, casename, openthread);
			openthread.start();
			dialog.setVisible(true);
		} else {
			//nothing todo
		}
		
		updateToolsAndMenus();

	}
	
	/**
	 * Informs the Listener that the model was loaded.
	 * Be sure that the model was loaded.
	 */
	public void modelLoaded() {
		if (getModel() == null)
			return;
		for (int i = 0; i < getListenerCount(); i++) {
			getListener(i).onModelLoaded(this, getModel());
		}
	}

	public void promptNew() {
		if (currentcase != null){
			if (!promptClose()){
				return;
			}
		}
		NewCaseDialog newcased = new NewCaseDialog(this);

		String casename = null;
		if (newcased.getExitAction() == newcased.OK) {
			casename = newcased.getNewCaseName();
		} else {
			return;
		}

		if (casename == null)
			return;

		Case newcase = null;
		try {
			boolean setAsCurrentCase = true;
			newcase = m4Interface.createCase(casename, setAsCurrentCase);
		} catch (M4Exception error) {
			M4Interface.print.doPrint(Print.ERROR,Resource.getString("ERROR_CREATE_CASE")+" \"" + casename + "\"\n" + error.getMessage(),error);
			JOptionPane.showMessageDialog(this,Resource.getString("ERROR_CREATE_CASE")+" \""  + casename + "\"\n" + error.getMessage(),
					Resource.getString("DIALOG_ERROR_TITLE"),JOptionPane.ERROR_MESSAGE);
			return;
		}

		if (newcase == null) {
			M4Interface.print.doPrint(Print.ERROR,Resource.getString("ERROR_CREATE_CASE")+" \""  + casename + "\"" );
			JOptionPane.showMessageDialog(this,Resource.getString("ERROR_CREATE_CASE")+" \""  + casename + "\"",
					Resource.getString("DIALOG_ERROR_TITLE"),JOptionPane.ERROR_MESSAGE);
			return;
		} else {
			try {
				newcase.store();
			} catch (M4Exception error) {
				M4Interface.print.doPrint(Print.ERROR,Resource.getString("ERROR_STORE_CASE")+" \"" + casename + "\"",error );
				JOptionPane.showMessageDialog(
					this,
					Resource.getString("ERROR_STORE_CASE")+" \"" + casename + "\"",
					Resource.getString("DIALOG_ERROR_TITLE"),
					JOptionPane.ERROR_MESSAGE);
				return;
			}
			m4Interface.releaseCase(casename);
			M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,Resource.getString("CREATED_NEW_CASE")+" "+casename);
			promptOpen(casename, true);
		}

	}

	public void saveModel() {
		Case ca=M4Interface.getCurrentCase();
//		MiningMartCase ca = ((MiningMartCase) this.currentModel);
		try {
			ca.store();
			this.currentModel.setDirty(false);
		} catch (M4Exception error) {
			M4Interface.print.doPrint(Print.ERROR,
				Resource.getString("ERROR_STORECASE")
				+ "\n"
				+ error.getMessage(),error);
			JOptionPane.showMessageDialog(
				this,
				Resource.getString("ERROR_STORECASE")
					+ "\n\n"
					+ error.getMessage(),
				Resource.getString("TXT_STORECASE"),
				JOptionPane.ERROR_MESSAGE);
			return;
		}
		M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,Resource.getString("CASE_SAVED"));
		((MiningMartMenuBar) getJMenuBar()).setItemState(
			Resource.getString("MENU_CASE")
				+ "."
				+ Resource.getString("MENU_CASE_SAVE"),
			false);

		((MiningMartToolBar) this.getToolbar()).enableTool(
			Resource.getString("TOOL_SAVECASE"),
			false);

	}

	/**
	 * Delete the current or another case.
	 */
	public void promptDeleteCase() {
		CaseTrasher trasher = new CaseTrasher(this);
		trasher.init();
		trasher.deleteCase();
		((MiningMartMenuBar) getJMenuBar()).setRecentCasesGUI();
	}

	/**
	 * Indicates wether the stepsettings are displayed or not.
	 */	
	public boolean isShowingStepSettings(){
		return this.showstepsettings;		
	}
	
	/**
	 * Indicates wether the settings of the <code>MiningMartStep</code> are displayed or not.
	 * @param step
	 */
	public boolean isShowingSettings(MiningMartStep step){
		if (stepsettings==null)
			return false;
		if (this.stepsettings.getMiningMartStep().getName().equals(step.getName()))
			return true;
		return false;
	}
	
	public boolean isShowingConceptPanel(MiningMartConcept concept){
		Concept theconcept=concept.getConcept();
		
		if (conceptpanel==null){
			return false;
		}
		
		return conceptpanel.getConcept().equals(theconcept);
	}
	
	/**
	 * Gets the panel of the stepsettings.
	 */
	public StepSettingsPanel getStepSettings(){
		return stepsettings;
	}
	
	public void setDataModel(Collection datamodel){
		this.datamodel=datamodel;
	}
	
	public Collection getDataModel(){
		return datamodel;
	}
	
	public void clearDataModel(){
		this.datamodel=null;
	}
	
	public boolean hasDataModel(){
		if (datamodel==null){
			return false;
		}
		if (datamodel.size()==0){
			return false;
		}
		return true;
	}

	/**
	 * Close the case.
	 */
	public boolean promptClose() {
//		this.showMemoryUsage();
		boolean back = true; //super.promptClose();

/*		if ((currentModel != null) && (this.currentModel.getDirty())
			&& (this.getViewMode() == EDITOR)) {
			int input =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("QUEST_SAVECLOSE"),
					Resource.getString("TXT_CLOSE"),
					JOptionPane.YES_NO_CANCEL_OPTION);

			if (input == JOptionPane.CANCEL_OPTION) {
				return false;
			} else {
				if (input == JOptionPane.YES_OPTION)
					saveModel();
			}
		}*/

		// bit of a hack to avoid deletion of documentation fields:
		MiningMartModel.mayChangeDocumentation = false;
		MiningMartModelFigureElement.mayChangeDocumentation = false;		
		if (!super.promptClose()){
			return false;
		}		
		MiningMartModel.mayChangeDocumentation = true;
		MiningMartModelFigureElement.mayChangeDocumentation = true;

		((MiningMartMenuBar) this.getJMenuBar()).promptCloseItemStates();
		((MiningMartToolBar) this.getToolbar()).promptCloseToolStates();
		clearDataModel();

		//Alle Komponenten nicht mehr anzeigen
		try {
			if ((concepttoolpanel!=null)&&(this.getViewMode() == EDITOR)){
				this.removeConceptTools();
			}
			if ((operatortoolpanel != null)&& (this.getViewMode() == EDITOR)) {
				this.removeOperatorTools();
			}
			if (showstepsettings) {
				removeStepSettingsPanel();
			}
			this.removeAnnotations();

			removeComponentFromTab(notepad);
			removeComponentFromTab(inspector);

			removeComponentFromTab(birdsEye);
			removeComponentFromTab(navigator);
			removeConceptPanel();
			this.mainpane.removeAllBut(logservice);

		} catch (Exception e) {
			//NullPointerException, wennn panel gar nicht dargestellt.
			M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
		}

		if ( ! MiningMartApplication.keepCase)
			this.currentcase = null;

		String casename=M4Interface.getCurrentCase().getName();
		if (( ! MiningMartApplication.keepCase) && M4Interface.getCurrentCase() != null) {
			m4Interface.releaseCaseWithoutStoring(M4Interface.getCurrentCase().getName());
			M4Interface.removeCurrentCase();
		}
		if (back){
			showComponentInTab(logservice,Application.PANE_CENTER,false);
			if ( ! MiningMartApplication.keepCase) M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,Resource.getString("CASE_CLOSED")+" \""+casename+"\"");
		}
		updateToolsAndMenus();
		System.gc(); 
//		this.showMemoryUsage();
		return back;
	}

	/**
	 * Exit the application.
	 */
	public void exit() {
		if ((currentModel != null) && (this.currentModel.getDirty())
			&& (this.getViewMode() == EDITOR)) {
			int input =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("QUEST_SAVECLOSE"),
					Resource.getString("TXT_CLOSE"),
					JOptionPane.YES_NO_CANCEL_OPTION);

			if (input == JOptionPane.CANCEL_OPTION) {
				return;
			} else if (input == JOptionPane.NO_OPTION) {
				//do nothing
			} else if (input == JOptionPane.YES_OPTION){
			     saveModel();
			}
		}

		if (getModel()!=null){
			String casename=M4Interface.getCurrentCase().getName();
			if (M4Interface.getCurrentCase() != null) {
				m4Interface.releaseCaseWithoutStoring(M4Interface.getCurrentCase().getName());
			}
		}

		saveParams();
		this.dispose();

		M4Interface.print.doPrint(Print.MAX,"\n----- " + getApplicationTitle() + " Version " + getApplicationVersion() + " exited. -----\n\n\n\n\n");
		System.exit(0);
	}

	/**
	 * Set the mode of the current case.
	 */
	public void promptSetMode() {
		SetModeDialog dia = new SetModeDialog(this, currentcase);
	}

	/**
	 * Exports the current case.
	 */
	public void exportCase() {
		if (currentcase == null)
			return;
		MiningMartApplication.caseExporter = new CaseExporter(this, currentcase);
		caseExporter.exportCase();
	}

	/**
	 * Imports a case.
	 */
	public void importCase() {
		if (currentcase != null) {
			if (!promptClose()){
				return;
			}
			//close currentcase before loading a new case
/*			int ret =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("QUEST_SAVECLOSE"),
					Resource.getString("TXT_CLOSE"),
					JOptionPane.YES_NO_OPTION,
					JOptionPane.ERROR_MESSAGE);
			if (ret == JOptionPane.YES_OPTION) {
				if (!promptClose()){
					return;
				}
			} else {
				return;
			}*/
		}

		MiningMartApplication.caseImporter = new CaseImporter(this);
		boolean imported = false;
		try {
			imported = caseImporter.importCase();
		} catch (IOException e) {
			M4Interface.print.doPrint(Print.ERROR,Resource.getString("IOEXCEPTION_IMPORT")+"\n"+e.getMessage(),e);
			JOptionPane.showMessageDialog(
				this,
				Resource.getString("IOEXCEPTION_IMPORT")+"\n" + e.getMessage(),
				Resource.getString("DIALOG_ERROR_TITLE"),
				JOptionPane.ERROR_MESSAGE);
			return;
		}

		if (imported) {
			M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,Resource.getString("CASE_IMPORTED")+" \""+M4Interface.getCurrentCase().getName()+"\"");
			boolean openCaseForUpdating = true;
			promptOpen(M4Interface.getCurrentCase().getName(),openCaseForUpdating);
		}
	}

	/**
	 * Gets the actual casename.
	 */
	public String getActualCaseName() {
		return this.actualcasename;
	}

	/**
	 * Sets the actual casename.
	 */
	public void setActualCaseName(String name) {
		this.actualcasename = name;
	}

	/**
	 * Methode, die f\x{FFFD}r den Navigator f\x{FFFD}r alle Modellelemente das erzeugen der Elemente nochmals wiederholt. N\x{FFFD}tig, damit
	 * nach dem Laden eines Modells richtig initialisiert ist.
	 * @param parentElement WurzelElement des Modells
	 * @param parentNode Wurzelknoten des Navigationsbaumes
	 */
	private void fireTraverseModel(ModelFigureElement parentElement) {
		// \x{FFFD}ber alle Kinder Iterieren und auf dem entsprechenden VaterKnoten onCreateChild aufrufen
		for (int i = 0; i < parentElement.getChildCount(); i++) {
			ModelFigureElement childElement = parentElement.getChild(i);
			navigator.onCreateChild(parentElement, childElement);

			fireTraverseModel(childElement);
		}
	}

	/**
	 * Wie fireTraverseModel, aber f\x{FFFD}r die Connections.
	 */
	private void fireTraverseModel2(ModelFigureElement element) {

		if (element instanceof Model) {
			Model model = (Model) element;
			// \x{FFFD}ber alle Kinder Iterieren und auf dem entsprechenden VaterKnoten onCreateChild aufrufen
			for (int i = 0; i < model.getConnectionCount(); i++) {
				ModelConnectionElement childElement = model.getConnection(i);
				navigator.onCreateConnection(model, childElement);

			}
		}

			for (int i = 0; i < element.getChildCount(); i++) {
				ModelFigureElement childElement = element.getChild(i);
				fireTraverseModel2(childElement);
			}
	}


	/**
	 * Merges the selected steps and chains to a new chain.
	 */
	public void promptMergeChain() {
		try {

			//ich brauche jetzt dringend ein paar elemente
			FigureEnumeration enum = getMainPane().getDrawingView().selection();

			int size = 0;
			while (enum.hasNextFigure()) {
				size++;
				enum.nextFigure();
			}

			ModelFigureElement[] elements = new ModelFigureElement[size];
			ModelConnectionElement[] conns = new ModelConnectionElement[size];

			enum = getMainPane().getDrawingView().selection();
			Figure figure;
			int index = 0;
			while (enum.hasNextFigure()) {
				figure = enum.nextFigure();
				if (figure instanceof ModelFigure) {
					elements[index] = ((ModelFigure) figure).getElement();
				}
				if (figure instanceof ModelConnection) {
					conns[index] = ((ModelConnection) figure).getElement();
				}
				index++;
			}

			//es soll wenigstens ein Element in einer Chain enthalten sein	
			// sonst macht das zusammenfuehren zu einer chain keinen sinn	
			if (index == 0) {
				M4Interface.print.doPrint(Print.WARNING,"At least one step or chain must be selected for merging!");
//				System.out.println("index=" + index);
				return;
			}

			//Ich brauch zuerst das Elternmodell
			Model parentmodel = null;
			for (int i = 0; i < elements.length; i++) {
				if (elements[i] != null) {
					parentmodel = elements[i].getModel();
					break;
				}
			}
			if (parentmodel == null) {
//				System.out.println("es wurde kein Element ausgewaehlt.");
				return;
			}

			//Collenction of selected steps and chains				
			Collection stepsandchains = new LinkedList();

			//walks through all selected ModelFigureElements
			//adds them to the collection and removes them from the parentmodel

			((MiningMartCase) this.getModel()).setDeleteInDatabase(false,true);

			for (int i = 0; i < size; i++) {
				//ist es wirklich ein element
				if (elements[i] != null) {
					if (elements[i] instanceof MiningMartChain) {
						stepsandchains.add(
							((MiningMartChain) elements[i]).getChain());
						((MiningMartChain) elements[i]).destroy();
					}
					if (elements[i] instanceof MiningMartStep) {
						stepsandchains.add(
							((MiningMartStep) elements[i]).getStep());
						((MiningMartStep) elements[i]).destroy();
					}

				}
			}

			((MiningMartCase) this.getModel()).setDeleteInDatabase(true,true);

			//create new chain and add it to the parentmodel
			Chain newchain;
			String newchainname = new String(Resource.getString("CHAIN"));
			MiningMartChain subchain = null;

			if (parentmodel instanceof MiningMartCase) {
				MiningMartCase parentcase = (MiningMartCase) parentmodel;
				newchainname =
					parentcase.getTheCase().getValidName(
						newchainname,
						Chain.class);

				newchain =
					parentcase.getTheCase().createChain(
						newchainname,
						stepsandchains);

				subchain =
					parentcase.createMiningMartChain(
						parentmodel,
						newchain,
						this.getPointforOperator(),
						new Rectangle(35, 35));
				parentcase.getTheCase().addChain(newchain);

				parentcase.organizeTransitions(true);
			} else if (parentmodel instanceof MiningMartChain) {
				MiningMartChain parentchain = (MiningMartChain) parentmodel;

				newchainname =
					parentchain.getTheCase().getValidName(
						newchainname,
						Chain.class);
				newchain =
					parentchain.getChain().createSubChain(
						newchainname,
						stepsandchains);

				subchain =
					parentchain.createMiningMartChain(
						parentmodel,
						newchain,
						this.getPointforOperator(),
						new Rectangle(35, 35));

				parentchain.organizeTransitions(true);
			} else {
				//do nothing we have no more models
			}

			getMainPane().getDrawingView().drawAll(
				getMainPane().getDrawingView().getGraphics());
			
			fireTraverseModel(parentmodel);
			fireTraverseModel2(parentmodel);
		} catch (M4Exception error) {
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
		}

		M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,Resource.getString("MERGED_CHAIN"));

	}

	/**
	 * Dissolves the selected chain.
	 */
	public void promptUnmergeChain() {
		try {

			//ich brauche jetzt dringend das ausgewaehlte Chain-Element
			FigureEnumeration enum = getMainPane().getDrawingView().selection();

			int size = 0;
			while (enum.hasNextFigure()) {
				size++;
				enum.nextFigure();
			}
			if (size != 1) {
				return;
			}

			enum = getMainPane().getDrawingView().selection();
			ModelFigureElement element =
				((ModelFigure) enum.nextFigure()).getElement();

			if (!(element instanceof MiningMartChain)) {
				return;
			}

			MiningMartChain selchain = (MiningMartChain) element;
			//Ich brauch zuerts das Elternmodell
			Model parentmodel = (Model) selchain.getParent();

			if (parentmodel instanceof MiningMartCase) {
				((MiningMartCase) parentmodel).dissolveMiningMartChain(selchain);
			} else if (parentmodel instanceof MiningMartChain) {
				((MiningMartChain) parentmodel).dissolveMiningMartChain(
					selchain);
			}

			getMainPane().getDrawingView().drawAll(
				getMainPane().getDrawingView().getGraphics());

			fireTraverseModel(parentmodel);
			fireTraverseModel2(parentmodel);

		} catch (M4Exception error) {
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
		}
		M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,Resource.getString("UNMERGED_CHAIN"));

	}

	/**
	 * Edit the db-settings.
	 */
	public void promptEditDbSettings() {
		DbConfigEditor editor = new DbConfigEditor(this);
		editor.setRestartWarning(true);
		editor.init();
		if (editor.shouldRestart()) {
			exit();
		}
	}

	/**
	 * Shows all transitions.
	 */
	public void promptShowAllTransitions() {
		//zwei ausgewaehlte Figuren miteinander verbinden!

		FigureEnumeration enum = getMainPane().getDrawingView().selection();

		Figure figure;
		ModelFigureElement start = null, end = null;
		while (enum.hasNextFigure()) {
			figure = enum.nextFigure();
			if (figure instanceof LineConnection) {
				start =
					((ModelFigure) ((LineConnection) figure).startFigure())
						.getElement();
				end =
					((ModelFigure) ((LineConnection) figure).endFigure())
						.getElement();
			}
		}

		if ((start == null) && (end == null)) {
			//You have to select one connection
			return;
		}

		ExistingTransitionsDialog dialog =
			new ExistingTransitionsDialog(this, start, end);
	}

	/**
	 * Shows the settings of the selected step.
	 */
	public void showStepSettings() {
		if (!(getMainPane().getCurrentPanel() instanceof DrawingPanel)) {
			return;
		}

		DrawingPanel panel = (DrawingPanel) getMainPane().getCurrentPanel();
		MiningMartDrawingView view =
			(MiningMartDrawingView) panel.getDrawingView();

		MiningMartSelectionListener listener =
			view.getMiningMartSelectionListener(0);
		if (listener.isMiningMartStepSelected()) {
			showStepSettings(listener.getSelectedMiningMartStep());
		}
	}

	/**
	 * Shows the settings of the step.
	 */
	public void showStepSettings(MiningMartStep step) {
		if (showstepsettings) {
			this.removeComponentFromTab(stepsettings);
		}
		stepsettings = new StepSettingsPanel(this, step);
		showComponentInTab(stepsettings, Application.PANE_RIGHT, true);
		showstepsettings = true;
	}

	/**
	 * Removes the panel of the step-settings.
	 */
	public void removeStepSettingsPanel() {
			removeComponentFromTab(stepsettings);
			showstepsettings = false;
	}
	
	/**
	 * Shows the following ConceptPanel.
	 * @param panel
	 */
	public void showConceptPanel(ConceptPanel panel){
		if (conceptpanel!=null){
			removeConceptPanel();			
		}
		conceptpanel=panel;
		showComponentInTab(conceptpanel, Application.PANE_RIGHT, true);
	}
	
	/**
	 * Removes the current ConceptPanel.
	 *
	 */
	public void removeConceptPanel(){
		if (conceptpanel!=null){
			removeComponentFromTab(conceptpanel);
		}
	}

	/**
	 * Sets the <code>OperatorToolPanel</code>.
	 */
	public void setOperatorToolPanel(OperatorToolPanel panel) {
		this.operatortoolpanel = panel;
	}

	/**
	 * Gets the <code>OperatorToolPanel</code>.
	 */
	public OperatorToolPanel getOperatorToolPanel() {
		return this.operatortoolpanel;
	}

	/**
	 * Sets the <code>ConceptToolPanel</code>.
	 */
	public void setConceptToolPanel(ConceptToolPanel panel) {
		this.concepttoolpanel = panel;
	}

	/**
	 * Gets the <code>onceptToolPanel</code>.
	 */
	public ConceptToolPanel getConceptToolPanel() {
		return this.concepttoolpanel;
	}


	/**
	 * Gets the access-mode of the case. Readable or not.
	 */
	public boolean isReadOnly() {
		if (getViewMode() == VIEWER) {
			return true;
		}
		return false;
	}

	/**
	 * Refreshs the CompilerAccess.
	 */
	public void refreshCompilerAccess() {
		try {
			compilerAccess =
				new CompilerAccessLogic(M4Interface.getInstance().getM4db(), M4Interface.print);
			M4Interface.setCurrentCompilerAccess(compilerAccess);
		} catch (Exception e) {
			M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
		}
	}

	/**
	 * Compiles the selected step.
	 */
	public void compileStep() {

		if (!(getMainPane().getCurrentPanel() instanceof DrawingPanel)) {
			return;
		}

		DrawingPanel panel = (DrawingPanel) getMainPane().getCurrentPanel();
		MiningMartDrawingView view =
			(MiningMartDrawingView) panel.getDrawingView();

		MiningMartSelectionListener listener =
			view.getMiningMartSelectionListener(0);
		if (!listener.isMiningMartStepSelected()) {
			return;
		}

		MiningMartStep mmStep = listener.getSelectedMiningMartStep();
		final long stepID = mmStep.getStep().getId();
		boolean isReady = false;

		boolean compile = true;		
		boolean check=true;

		String errorMsg = "";
		Step invalidStep = null;
		try{
			invalidStep = mmStep.getStep();
			check=mmStep.getStep().checkInputParameterEntries();
			if (!mmStep.getStep().checkOutputParameterEntries()){
				check=false;
			}
		}catch(M4Exception error){
			// M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			check=false;
			errorMsg = error.getMessage();
		}

		if (!check){
			compile =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("COMPILE_VALIDITY_STEP")+"\n"+
				 		Resource.getString("COMPILE_VALIDITY_CAUSE")+
						" (Step '"+invalidStep.getName()+"')\n" + errorMsg +
						"\nContinue compiling?",
					Resource.getString("COMPILE_VALIDITY_TITLE"),
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.ERROR_MESSAGE)
					== JOptionPane.OK_OPTION;
			if (!compile) {
				return;
			}
		}		

		try {
			isReady = getCompilerAccess().isReadyForCompilation(stepID);
		} catch (M4CompilerInterfaceError e) {
			M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
			refreshCompilerAccess();
		} catch (RemoteException re) {
			M4Interface.print.doPrint(Print.ERROR,re.getMessage(),re);
			JOptionPane.showMessageDialog(
				this,
				Resource.getString("COMPILER_ACCESS_ERROR_LINE1")+"\n"+
				Resource.getString("COMPILER_ACCESS_ERROR_LINE2")+"\n"+
				Resource.getString("COMPILER_ACCESS_ERROR_LINE3"),
				Resource.getString("COMPILER_ACCESS_ERROR_TITLE"),
				JOptionPane.ERROR_MESSAGE);
			refreshCompilerAccess();
			return;
		}

		if (!isReady) {
				JOptionPane.showMessageDialog(
					this,
					Resource.getString("COMPILE_NOT_STEP_LINE1")+"\n"+
					Resource.getString("COMPILE_NOT_STEP_LINE2"),
					Resource.getString("COMPILE_NOT_STEP_TITLE"),
					JOptionPane.ERROR_MESSAGE);
				return;
		}
		M4Interface.print.doPrint(
			Print.COMPILER_CASE_CONTROL,
			Resource.getString("START_COMPILING"));

		compilerThread =
			new CompilerThread(this, CompilerThread.COMPILE_STEP, stepID);
		compilerThread.start();
		//		openCompilerLogWindow();

	}

	/**
	 * Compiles all steps in the case.
	 */
	public void compileAll() {
		
		boolean check=true;

		boolean compile=true;

		Step step = null;
		Step invalidStep = null;
		String errorMsg = "";
		try{
			Collection coll=M4Interface.getCurrentCase().getAllStepNames();
			Iterator iter=coll.iterator();
			while (iter.hasNext()){
				step=M4Interface.getCurrentCase().getStepByName((String) iter.next());
				invalidStep = step;
			
				if (!step.checkInputParameterEntries()){
					check=false;
				}
				if (!step.checkOutputParameterEntries()){
					check=false;
				}
			}
		}catch(M4Exception error){
			// M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			check=false;
			errorMsg = error.getMessage();
		}

		if (!check){
			compile =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("COMPILE_VALIDITY_ALL_STEPS")+"\n"+
						 Resource.getString("COMPILE_VALIDITY_CAUSE")+
					     " (Step '"+invalidStep.getName()+"')\n" + errorMsg +
						 "\nContinue compiling?",
					Resource.getString("COMPILE_VALIDITY_TITLE"),
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.ERROR_MESSAGE)
					== JOptionPane.OK_OPTION;
			if (!compile) {
				return;
			}
		}		
		
		
		
		
		M4Interface.print.doPrint(
			Print.COMPILER_CASE_CONTROL,
			Resource.getString("START_COMPILING"));

		compilerThread =
			new CompilerThread(this, CompilerThread.COMPILE_ALL, 0);
		compilerThread.start();
		//		openCompilerLogWindow();
	}

	/**
	 * Compiles until the selected step.
	 */
	public void compileUntil() {
		if (!(getMainPane().getCurrentPanel() instanceof DrawingPanel)) {
			return;
		}

		DrawingPanel panel = (DrawingPanel) getMainPane().getCurrentPanel();
		MiningMartDrawingView view =
			(MiningMartDrawingView) panel.getDrawingView();

		MiningMartSelectionListener listener =
			view.getMiningMartSelectionListener(0);
		if (!listener.isMiningMartStepSelected()) {
			return;
		}

		MiningMartStep mmStep = listener.getSelectedMiningMartStep();
		final long stepID = mmStep.getStep().getId();


		boolean check=true;

		boolean compile=true;
		Step invalidStep = null;
		String errorMsg = "";
		try{
			Collection coll=M4Interface.getCurrentCase().getStepsToCompileBefore(mmStep.getStep(),true);
			Iterator iter=coll.iterator();
			Step step;
			while (iter.hasNext()){
				step=(Step) iter.next();
				invalidStep = step;
				if (!step.checkInputParameterEntries()){
					check=false;
				}
				if (!step.checkOutputParameterEntries()){
					check=false;
				}
			}
			invalidStep = mmStep.getStep();
			if (!mmStep.getStep().checkInputParameterEntries()){
				check=false;
			}
			if (!mmStep.getStep().checkOutputParameterEntries()){
				check=false;
			}
		}catch(M4Exception error){
			// M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			check=false;
			errorMsg = error.getMessage();
		}

		if (!check){
			compile =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("COMPILE_VALIDITY_ALL_STEPS")+"\n"+
					 	Resource.getString("COMPILE_VALIDITY_CAUSE")+
						" (Step '"+invalidStep.getName()+"')\n" + errorMsg +
						"\nContinue compiling?",
					Resource.getString("COMPILE_VALIDITY_TITLE"),
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.ERROR_MESSAGE)
					== JOptionPane.OK_OPTION;
			if (!compile) {
				return;
			}
		}		



		M4Interface.print.doPrint(
			Print.COMPILER_CASE_CONTROL,
			Resource.getString("START_COMPILING"));

		compilerThread =
			new CompilerThread(this, CompilerThread.COMPILE_UNTIL_STEP, stepID);
		compilerThread.start();
		//			openCompilerLogWindow();
	}

	/**
	 * Compiles from the selected step.
	 */
	public void compileFrom() {
		if (!(getMainPane().getCurrentPanel() instanceof DrawingPanel)) {
			return;
		}

		DrawingPanel panel = (DrawingPanel) getMainPane().getCurrentPanel();
		MiningMartDrawingView view =
			(MiningMartDrawingView) panel.getDrawingView();

		MiningMartSelectionListener listener =
			view.getMiningMartSelectionListener(0);
		if (!listener.isMiningMartStepSelected()) {
			return;
		}

		MiningMartStep mmStep = listener.getSelectedMiningMartStep();
		final long stepID = mmStep.getStep().getId();

		boolean check=true;

		boolean compile=true;
		Step invalidStep = null;
		String errorMsg = "";
		try{
			Collection coll=M4Interface.getCurrentCase().getDependentStepsFor(mmStep.getStep());
			Iterator iter=coll.iterator();
			Step step;
			while (iter.hasNext()){
				step=(Step) iter.next();
				invalidStep = step;
				if (!step.checkInputParameterEntries()){
					check=false;
				}
				if (!step.checkOutputParameterEntries()){
					check=false;
				}
			}
			invalidStep = mmStep.getStep();
			if (!mmStep.getStep().checkInputParameterEntries()) {
				check = false;
			}
			if (!mmStep.getStep().checkOutputParameterEntries()) {
				check = false;
			}
		}catch(M4Exception error){
			// M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			check=false;
			errorMsg = error.getMessage();
		}

		if (!check){
			compile =
				JOptionPane.showConfirmDialog(
					this,
					Resource.getString("COMPILE_VALIDITY_ALL_STEPS")+"\n"+
					 	Resource.getString("COMPILE_VALIDITY_CAUSE")+
						" (Step '"+invalidStep.getName()+"')\n" + errorMsg +
						"\nContinue compiling?",
					Resource.getString("COMPILE_VALIDITY_TITLE"),
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.ERROR_MESSAGE)
					== JOptionPane.OK_OPTION;
			if (!compile) {
				return;
			}
		}		


		boolean isReady = false;

		try {
			isReady = getCompilerAccess().isReadyForCompilation(stepID);
		} catch (M4CompilerInterfaceError error) {
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
		} catch (RemoteException re) {
			M4Interface.print.doPrint(Print.ERROR,re.getMessage(),re);
			JOptionPane.showMessageDialog(
				this,
				Resource.getString("COMPILER_ACCESS_ERROR_LINE1")+"\n"+
				Resource.getString("COMPILER_ACCESS_ERROR_LINE2")+"\n"+
				Resource.getString("COMPILER_ACCESS_ERROR_LINE3"),
				Resource.getString("COMPILER_ACCESS_ERROR_TITLE"),
				JOptionPane.ERROR_MESSAGE);
			refreshCompilerAccess();
			return;
		}

		if (isReady) {
			M4Interface.print.doPrint(
				Print.COMPILER_CASE_CONTROL,
				Resource.getString("START_COMPILING"));

			compilerThread =
				new CompilerThread(
					this,
					CompilerThread.COMPILE_FROM_STEP,
					stepID);
			compilerThread.start();
			//			openCompilerLogWindow();
		} else {
			JOptionPane.showMessageDialog(
				this,
				Resource.getString("COMPILE_NOT_STEP_LINE1")+"\n"
					+ Resource.getString("COMPILE_NOT_STEP_LINE2"),
				Resource.getString("COMPILE_NOT_STEP_TITLE"),
				JOptionPane.ERROR_MESSAGE);
		}
	}

	/**
	 * Kills the compiler thread.
	 * Kills a running compilation thread on the compiler server.
	 * a method on the CompilerServer is called which is responsible to clean up
	 */
	public void killCompilation() {
		try {
			// debug M4 interface:
			// Application.getCompilerAccess().killCompilerThread(((com.syllogic.miningmart.m4.Case)Application.m4Case).getId());
			getCompilerAccess().killCompilerThread(M4Interface.getCurrentCase().getId());
		} catch (RemoteException re) {
			M4Interface.print.doPrint(Print.ERROR,re.getMessage(),re);
		}
		M4Interface.print.doPrint(Print.COMPILER_CASE_CONTROL,"Killed Compilation.");
		((MiningMartMenuBar) getJMenuBar()).promptDoneCompilationItemStates();
		((MiningMartToolBar) getToolbar()).promptDoneCompilationItemStates();
	}

	/**
	 * Collects and deletes the garbage from the current case.
	 */
	public void collectGarbage() {

		GarbageCollector collector =
			new GarbageCollector(this, M4Interface.getCurrentCase());
	}

	/**
	 * Shows the annotations.
	 */
	public void showAnnotations() {
		((MiningMartMenuBar) this.getJMenuBar()).show_annotations.setSelected(
			true);
		showComponentInTab(hypertextViewer, PANE_RIGHT, true);
	}

	/**
	 * Removes the annotations.
	 */
	public void removeAnnotations() {
		((MiningMartMenuBar) this.getJMenuBar()).show_annotations.setSelected(
			false);
		removeComponentFromTab(hypertextViewer);
	}
  
	/**
	 * Shows the <code>OperatorToolPanel</code>.
	 */
	public void showOperatorTools() {
		((MiningMartMenuBar) this.getJMenuBar()).show_tools.setSelected(true);
		showComponentInTab(
			operatortoolpanel.getOperatorToolPanel(),
			PANE_RIGHT,
			true);
	}

	/**
	 * Removes the <code>OperatorToolPanel</code>.
	 */
	public void removeOperatorTools() {
		((MiningMartMenuBar) this.getJMenuBar()).show_tools.setSelected(
			false);
		removeComponentFromTab(operatortoolpanel.getOperatorToolPanel());
	}
	
	/**
	 * Shows the <code>ConceptToolPanel</code>.
	 */
	public void showConceptTools() {
		((MiningMartMenuBar) this.getJMenuBar()).show_tools.setSelected(true);
		showComponentInTab(
			concepttoolpanel.getConceptToolPanel(),
			PANE_RIGHT,
			true);
	}
	
	/**
	 * Removes the <code>ConceptToolPanel</code>.
	 */
	public void removeConceptTools() {
		((MiningMartMenuBar) this.getJMenuBar()).show_tools.setSelected(
			false);
		removeComponentFromTab(concepttoolpanel.getConceptToolPanel());
	}


	/**
	 * @see org.musoft.limo.application.Application#createLogger()
	 */
	public Logger createLogger() {
		return M4Interface.print.getLogger();
	}

	/* (non-Javadoc)
	 * @see org.musoft.limo.application.Application#getApplicationTitle()
	 */
	public String getApplicationTitle() {
		return Resource.getString("APP_TITLE");
	}

	/* (non-Javadoc)
	 * @see org.musoft.limo.application.Application#getApplicationVersion()
	 */
	public String getApplicationVersion() {
		return Resource.getString("APP_VERSION");
	}



	/* (non-Javadoc)
	 * @see org.musoft.limo.application.Application#getConfigPath()
	 */
	protected File getConfigPath() {
//		File home = new File(getUserHome() + File.separatorChar + ".mmart");
		File home = new File(System.getProperty(MiningMartApplication.SYSTEM_PROP_MM_HOME) + File.separatorChar + "config");
		File file = new File(home, getApplicationName() + ".cfg");
	    
		return file;
	}



	/* (non-Javadoc)
	 * @see org.musoft.limo.application.Application#checkToolsAndMenus()
	 */
	protected void checkToolsAndMenus() {
		super.checkToolsAndMenus();

		String title = new String(Resource.getString("APP_TITLE"));
		if (currentModel != null)
			title += " - [" + currentModel.getName() + "]";
		if ((currentModel != null) && (getViewMode()==EDITOR) && currentModel.getDirty())
			title += "*"; 
		if ((currentModel != null) &&(getViewMode() != EDITOR))
			title += " - " + Resource.getString("TXT_READONLY");

		setTitle(title);

		fireStateChanged();
	}
	
	/**
	 * Returns the number of BaseAttributes displayed in a Concept!
	 */
	public int getNumberOfFeatures(){
		return nrFeatures;		
	}
	
	public void setWhichLinksToDraw(boolean subconc, boolean rels, boolean projs) {
		this.drawProjections = projs;
		this.drawRelationships = rels;
		this.drawSubconceptLinks = subconc;
	}
	
	public boolean shouldDrawSubconceptLinks() {
		return this.drawSubconceptLinks;
	}
	
	public boolean shouldDrawRelationships() {
		return this.drawRelationships;
	}
	
	public boolean shouldDrawProjections() {
		return this.drawProjections;
	}
	
	/**
	 * Sets the number of BaseAttributes displayed in a Concept!
	 */
	public void setNumberOfFeatures(int nr){
		this.nrFeatures=nr;
	}
	
	
	/**
	 * @see org.musoft.limo.application.Application#checkToolsAndMenus()
	 */
	public void updateToolsAndMenus(){
		checkToolsAndMenus();
	}

	public static void main(String[] args) {
		
		// check existence of the MiningMartHome properties:
		String path = System.getProperty("user.dir");
		if (path.toLowerCase().endsWith("bin")) {
			path = path.substring(0, path.length() - 3);
		}
		if (path.toLowerCase().endsWith("bin" + File.separator)) {
			path = path.substring(0, path.length() - 4);
		}
		if ( ! path.endsWith(File.separator)) {
			path += File.separator;
		}
		String filename = path + "config" + File.separator + "MiningMartHome.properties";
		File f = new File(filename);
		String homePropertiesFilename = null;
		if ( ! f.exists()) {
			String homepath = JOptionPane.showInputDialog(null,
						"No file 'MiningMartHome.properties' found. The system will create one\n" +
						"automatically. Please provide the MiningMart home directory, which is the\n" +
						"path up to and including 'MiningMart' or 'MiningMart-1.0'.",
						path);
			homePropertiesFilename = MmInstallerTools.createHomePropertiesFile(homepath);
			if (homePropertiesFilename == null) {
				JOptionPane.showConfirmDialog(
						null,
						"Error accessing 'MiningMartHome.properties'! Please start again.",
						"Error starting the system",
						JOptionPane.OK_CANCEL_OPTION,
						JOptionPane.ERROR_MESSAGE);
				System.exit(-1);
			}
		}
		else {
			homePropertiesFilename = filename;
		}
		
		// read resouces:
		System.out.print("Loading Resources...");
		try {
			MmInstallerTools.readSystemPropsFromHomeProperties(homePropertiesFilename);
			Resource.addSpecResources("operators");
			Resource.addSpecResources("mmart_constants");
			Resource.addSpecResources("mmart_menu");
			Resource.addSpecResources("mmart_toolbar");
			setDefaultProperties();
		}
		catch (Exception e) {
			JOptionPane.showConfirmDialog(
					null,
					"Error reading resources! Please check the location of the '*.properties' files and start again. Error message:\n" +
					e.getMessage(),
					"Error starting the system",
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}
		System.out.println("done.");
				
		// check if anything has to be installed:
		boolean installationOk = false;
		if ( ! (installationOk = MmInstallerTools.installationIsValid())) {
			installationOk = MmInstallerTools.doInstallation(path);
		}
		if ( ! installationOk) {
			JOptionPane.showConfirmDialog(
					null,
					"Installation failed. Please start again and try new installation settings.",
					"Error during installation",
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}
		
		//
		// Show startup screen
		// 
		StartWindow startupWindow = new StartWindow();

		startupWindow.setMessage(Resource.getString("STARTWINDOW_CREATEFRAME"));	
		
		// A proper DB connection is e.g. required to set up the GUI menues,
		// so it does not make sense to run into a messed up system state:
		boolean canceled = false;
		while ((validateDbConfigFile() == false) && (canceled == false)) { 
			startupWindow.setVisible(false);
			DbConfigEditor editor = new DbConfigEditor(null);
			editor.setRestartWarning(false);
			editor.init();
			canceled = editor.isCanceled();
		}
		if (!validateDbConfigFile()) {
			System.err.println("\n** The database connection could not be established. **");
			System.err.println("** Could not launch the system. **\n");
			System.exit(-1);
		}
		
		MiningMartApplication m = new MiningMartApplication();
		startupWindow.setMessage(Resource.getString("STARTWINDOW_SHOWFRAME"));
		// Hide startup screen
		startupWindow.setVisible(false);
		startupWindow.dispose();
	}	
	
	private static boolean validateDbConfigFile() {
		String dbConfigPath = System.getProperty(M4Interface.SYSTEM_PROP_DB_CONFIG_PATH);
		if (dbConfigPath == null || dbConfigPath.length() == 0) {
			System.err.println(
					"Fatal error: Could not read System property "
					+ M4Interface.SYSTEM_PROP_DB_CONFIG_PATH
					+ " to set up database connections!!");
			return false;
		}
		else {
			try {
				ConfigReader cr = new ConfigReader(dbConfigPath);
			}
			catch (M4Exception e) {
				System.err.println(
						"Fatal error: File specified by System property "
						+ M4Interface.SYSTEM_PROP_DB_CONFIG_PATH
						+ " does not contain valid information to connect to database.");
				return false;
			}
			
			M4Interface m4i = M4Interface.getInstance();
			return (m4i.getM4db() != null);
		}
	}	
	
	private long calculateMemoryUsage() {
		long mem = Runtime.getRuntime().totalMemory() -
		  Runtime.getRuntime().freeMemory();
		return mem;
	  }

	  private void showMemoryUsage() {
		long mem = calculateMemoryUsage();
		System.out.println(
		  "Memory used " +mem/1024 + " kbytes");
	  }
	
}
/*
$Log: MiningMartApplication.java,v $
Revision 1.19  2006/04/11 14:10:15  euler
Updated license text.

Revision 1.18  2006/04/06 16:31:15  euler
Prepended license remark.

Revision 1.17  2006/03/29 09:50:47  euler
Added installation robustness.

Revision 1.16  2006/03/24 14:19:31  euler
Added concept links preferences

Revision 1.15  2006/03/23 11:13:46  euler
Improved exception handling.

Revision 1.14  2006/03/22 16:49:27  euler
*** empty log message ***

Revision 1.13  2006/03/22 13:08:52  euler
*** empty log message ***

Revision 1.12  2006/03/19 16:59:20  scholz
robustification against missing or invalid db.config file

Revision 1.11  2006/03/16 14:53:38  euler
*** empty log message ***

Revision 1.10  2006/03/02 16:49:59  euler
Many bugfixes

Revision 1.9  2006/01/27 17:27:17  euler
Bugfix

Revision 1.8  2006/01/12 09:51:14  hakenjos
releaseCaseWithoutStoring also in promptClose()

Revision 1.7  2006/01/12 09:31:09  hakenjos
Changes in exit().

Revision 1.6  2006/01/11 17:15:31  euler
Small bugfix

Revision 1.5  2006/01/11 16:57:09  euler
Small bugfix

Revision 1.4  2006/01/10 10:08:37  hakenjos
First load the verbosity-level from system-propertioes
and then have a look in the preferences.

Revision 1.3  2006/01/10 08:12:26  hakenjos
Fixed Bug promptClose()

Revision 1.2  2006/01/09 14:32:22  euler
Changed handling of preferred print verbosity
in method loadParams()

Revision 1.1  2006/01/03 09:54:26  hakenjos
Initial version!

*/
