package diploma;

import javax.swing.*;
import java.sql.*;
import javax.swing.text.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.util.*;
import java.io.*;

public class Interogare extends JFrame implements ActionListener,ItemListener,
	ListSelectionListener, MouseListener, ChangeListener {
		StringBuffer comandaString = new StringBuffer(), comandaHtmlString  = 
		new StringBuffer(), selString = new StringBuffer(),
		selHtmlString = new StringBuffer(), orderString = new StringBuffer(), 
		orderHtmlString = new StringBuffer(), groupString = new StringBuffer(), 
		groupHtmlString = new StringBuffer(), havingString = new StringBuffer(),
		havingHtmlString = new StringBuffer();
	//private boolean editManComSql = false;	//e editată manual comanda SQL ?
	private String numeBazaDeDate;
		DouaListeSiButoanePattern selTab2LSi2B, selCp2LSi2B, orderCp2LSi2B, 
			groupCp2LSi2B;
		WherePanel wherePanel, havingWherePanel;
		JoinPanel joinPanel;
	private JTabbedPane criteriiTabbedPane;
		EditManualPanel editManPanel;
	private JCheckBox distinctCheckBox;
		JLabel exprAritmLabel, numeNouCpLabel;
		JTextField exprAritmTxFld, numeNouCpTxFld, limitTxField;
	private JRadioButton orderAscRadioButton, orderDescRadioButton,
		groupAscRadioButton, groupDescRadioButton;
	private JButton validOrderButton, validGroupButton, selectButton, 
		inchidButton;
	//numele și numele noi cu care se vor afișa câmpurile :
	private Hashtable<String, String> numeNouCpHash;
//	private Hashtable<String, TabelMysqlObj> tabeleHash; 
	InterfataGrafica interfataGrafica;	

	class AscultaLaText implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (e.getActionCommand().equals("nume nou")) {
				if (! selCp2LSi2B.lista2.isSelectionEmpty()) {
					String nmVechi = selCp2LSi2B.lista2.getSelectedValue(
						).toString();
					numeNouCpHash.put(nmVechi, numeNouCpTxFld.getText());
					formareSelect();
					formareComanda();
					for (int i = 0; i < havingWherePanel.numeCpCBoxModel.getSize(
						); i++) {
						if (havingWherePanel.numeCpCBoxModel.getElementAt(
							i).toString().equals(nmVechi)) {
						//înlocuim vechiul nume cu cel nou în havingWherePanel
							havingWherePanel.numeCpCBoxModel.removeElement(
								nmVechi);
							havingWherePanel.numeCpCBoxModel.addElement(
								numeNouCpTxFld.getText());
						}
					}
				}
				else {
					JOptionPane.showMessageDialog(null, "Selectați un câmp "
					+ "din listă, scrieți noul nume\nși apăsați <enter> ");
					selCp2LSi2B.lista2.requestFocusInWindow();
				}
				numeNouCpTxFld.setText("");	
			}
		}
	}

//clasa pt obiectele selTab2LSi2B, selCp2LSi2B, orderCp2LSi2B, groupCp2LSi2B	
	class AscultaLaModifLista implements ListDataListener {
		private DouaListeSiButoanePattern legat;	//la care ascultă
		
		public AscultaLaModifLista(DouaListeSiButoanePattern legat) {
			this.legat = legat;
		}
		public void contentsChanged(ListDataEvent e) {
			legat.activDezactivBut();
			DefaultListModel srcDlm = (DefaultListModel)e.getSource();
			DefaultListModel dlm12 = (DefaultListModel)
				selTab2LSi2B.lista2.getModel();
			DefaultListModel dlm22 = (DefaultListModel)
				selCp2LSi2B.lista2.getModel();
			if (srcDlm == dlm12 || srcDlm == dlm22) {
				formareSelect();
				formareComanda();
				if (srcDlm == dlm22) {	//verificăm dc. e o fcț. agregată
					if (existaFctAgregata())
						groupCp2LSi2B.buton1.setEnabled(true);
					else {
						((DefaultListModel)groupCp2LSi2B.lista2.getModel(
							)).removeAllElements();
						groupCp2LSi2B.buton1.setEnabled(false);
					}
				}
			}
		}
		public void intervalAdded(ListDataEvent e) {
			legat.activDezactivBut();
			contentsChanged(e);
		}
		public void intervalRemoved(ListDataEvent e) {
			legat.activDezactivBut();
			contentsChanged(e);
		}
	}

 	 class AscLaButOrdSiAgreg implements ActionListener {
 	 	public void actionPerformed(ActionEvent e) {
 	 		if (((JButton)e.getSource()).equals(orderCp2LSi2B.buton1)) {
 	 			String[] exceptArray = {"expresie aritmetică", "SUM", "COUNT",
 	 				"MIN", "MAX", "AVG"};
 	 			if (orderCp2LSi2B.lista1.isSelectionEmpty()) return;
 	 			String nmCp = (String) orderCp2LSi2B.lista1.getSelectedValue();
 	 			for (String exceptCpCrt : exceptArray)
 	 				if (exceptCpCrt.equals(nmCp)) return;
 	 			if (nmCp.endsWith(".*")) return;
 	 			orderCp2LSi2B.select();
 	 		}
 	 		else if (((JButton)e.getSource()).equals(orderCp2LSi2B.buton2))
 	 			orderCp2LSi2B.deselect();
 	 		else if (((JButton)e.getSource()).equals(groupCp2LSi2B.buton1)) {
 	 			if (! existaFctAgregata())
 	 				return;
 	 			String[] exceptArray = {"expresie aritmetică", "SUM", "COUNT",
 	 				"MIN", "MAX", "AVG"};
 	 			if (groupCp2LSi2B.lista1.isSelectionEmpty()) return;
 	 			String nmCp = (String) groupCp2LSi2B.lista1.getSelectedValue();
 	 			for (String exceptCpCrt : exceptArray)
 	 				if (exceptCpCrt.equals(nmCp)) return;
 	 			if (nmCp.endsWith(".*")) return;
 	 			groupCp2LSi2B.select();
 	 		}
 	 		else if (((JButton)e.getSource()).equals(groupCp2LSi2B.buton2))
 	 			groupCp2LSi2B.deselect();
 	 	}
 	 }

	//ascultă la butoanele selecției :	
	class AscultaLaButSel implements ActionListener {
		private Interogare parinte;
		public AscultaLaButSel(Interogare parinte) {
			this.parinte = parinte;
		}
		public void actionPerformed(ActionEvent e) {
	//selectare tabel :
			if (((JButton)e.getSource()).equals(selTab2LSi2B.buton1)) {
				if (selTab2LSi2B.lista1.isSelectionEmpty())
					return;
				String nmTab = (String) selTab2LSi2B.lista1.getSelectedValue();
				ObjectInputStream objInStr = null;
				try {
					objInStr = new ObjectInputStream(
						new FileInputStream(numeBazaDeDate + "\\" + nmTab + 
						".txt"));
				}
				catch (FileNotFoundException fileExc) {fileExc.getMessage();}
				catch (IOException ioExc) {ioExc.getMessage();}
				TabelMysqlObj tabObj = null;
				try {
					tabObj = (TabelMysqlObj)objInStr.readObject();
					if (objInStr != null) objInStr.close();
				}
				catch (ClassNotFoundException classExc) {
					classExc.getMessage();
				}
				catch(IOException except) {except.getMessage();}
	/*			if (tabObj == null) return;
					tabeleHash.put(nmTab, tabObj);	//adaugă tabelul la tabeleHash
	*/		//adăugăm tabelul în lista 2:
				if (((DefaultListModel)selTab2LSi2B.lista2.getModel()).contains(
					nmTab))
					return;	//tabelul există deja în listă
				((DefaultListModel)selTab2LSi2B.lista2.getModel()).addElement(
					nmTab);
				//adăugăm tabelul în joinTable
				joinPanel.tab1CBoxModel.addElement(nmTab);
				joinPanel.tab2CBoxModel.addElement(nmTab);
		//mai adăugăm un rând în tabelul joinTable
				if (((DefaultListModel)selTab2LSi2B.lista2.getModel()).getSize(
					) > joinPanel.joinTable.getRowCount() + 1) {
					String[] rdGol = {"", "", "", "", ""};	
					((DefaultTableModel) joinPanel.joinTable.getModel(
						)).addRow(rdGol);	
					}
		//adăugăm toate cp. tabelului în lista 1 de la câmpuri și de asemenea 
		//în lista de câmpuri din tabelul where :
				Hashtable<String, Atribute> arrCpAtribHash = 
					tabObj.getArrayCpAtribHash();
				DefaultListModel dlm21 = (DefaultListModel)
					selCp2LSi2B.lista1.getModel();
				for (Atribute atr : arrCpAtribHash.values()) {
					String nmCp = atr.getProperty("numeCamp");
					dlm21.insertElementAt(nmTab + "." + nmCp, 0);
					wherePanel.numeCpCBoxModel.insertElementAt(
						nmTab + "." + nmCp, 0);
					wherePanel.cpHash.put(nmTab + "." + nmCp,
						atr.getProperty("tipCamp") + 
						((atr.getProperty("lungCamp").equals("no")) ?
						"" : "(" + atr.getProperty("lungCamp") + ")"));
				}
			//inserăm și select * :
				dlm21.insertElementAt(nmTab + ".*", 0);
			}
		//deselectare tabel :	
			else if (((JButton)e.getSource()).equals(selTab2LSi2B.buton2)) {
				if (selTab2LSi2B.lista2.isSelectionEmpty())
					return;
				int answ = JOptionPane.showConfirmDialog(null, "Dacă eliminați "
					+ "un tabel, toate câmpurile\ntabelului vor dispare "
			 		+ "din clauza SELECT ! Ștergeți ?", "Avertisment", 
			 		JOptionPane.YES_NO_OPTION,	JOptionPane.WARNING_MESSAGE);
			 	if (answ == JOptionPane.NO_OPTION)
			 		return;
				String nmTab = (String) selTab2LSi2B.lista2.getSelectedValue();
			//ștergem tabelul :
				((DefaultListModel)selTab2LSi2B.lista2.getModel(
					)).removeElement(nmTab);
//				tabeleHash.remove(nmTab);
				//ștergem din joinTable
				joinPanel.tab1CBoxModel.removeElement(nmTab);
				joinPanel.tab2CBoxModel.removeElement(nmTab);
				//ștergem un rând din joinTable
				int nrRand = joinPanel.joinTable.getRowCount();
				boolean stersUnRand = false;
				for (int i = 0; i < nrRand; i++) {
					if (joinPanel.joinTable.getValueAt(i, 0).toString(
						).equals(nmTab) || joinPanel.joinTable.getValueAt(
						i, 3).toString().equals(nmTab)) {
						for (int j = 0; j < 5; j++)
							joinPanel.joinTable.setValueAt("", i, j);
						if (! stersUnRand && nrRand > 1) {
							((DefaultTableModel)joinPanel.joinTable.getModel(
								)).removeRow(i);
							i--;		//s-a șters un rând
							stersUnRand = true;
						}	
					}
				}
				if (! stersUnRand && nrRand > 1)
					((DefaultTableModel)joinPanel.joinTable.getModel(
						)).removeRow(nrRand - 1);	
			//ștergem toate câmpurile tabelului din lista1 a câmpurilor
			//pot intra în expresii, de aceea le ștergem pe acelea în care apar
			 	DefaultListModel dlm21 = (DefaultListModel)
					selCp2LSi2B.lista1.getModel();
				Object[] listCpArray = dlm21.toArray();
				for (int i = 0; i < listCpArray.length; i++) {
					String nmCpStr = (String) listCpArray[i];
	 				if (nmCpStr.indexOf(nmTab + ".") > -1) {
						dlm21.removeElement(nmCpStr);
					}
				}
			//ștergem toate câmpurile tabelului din lista2 a câmpurilor
			//pot intra în expresii, de aceea le ștergem pe toate în care apar
			 	DefaultListModel dlm22 = (DefaultListModel)
					selCp2LSi2B.lista2.getModel();
				for (Object nmCpObj : dlm22.toArray()) {
					String nmCpStr = (String) nmCpObj;
					if (nmCpStr.indexOf(nmTab + ".") > -1) {
						dlm22.removeElement(nmCpObj);
						//ștergem și din tabelul having, dc. apare
						String nmNouStr = numeNouCpHash.get(nmCpStr);
						if (nmNouStr != null)
							nmCpStr = nmNouStr;

						for (int j = 0; j < 
							havingWherePanel.numeCpCBoxModel.getSize(); j++) {
							if (havingWherePanel.numeCpCBoxModel.getElementAt(
								j).toString().equals(nmCpStr))
								havingWherePanel.numeCpCBoxModel.removeElementAt(
									j);	
						}
					}
				}
				if (! existaFctAgregata())
					groupCp2LSi2B.buton1.setEnabled(false);
				//ștergem cp. tabelului din lista cu selecțiile de ordonare :
			 	DefaultListModel dlm32 = (DefaultListModel)
			 		orderCp2LSi2B.lista2.getModel();
				for (Object nmCpObj : dlm32.toArray()) {
					String nmCpStr = (String) nmCpObj;
					if (nmCpStr.indexOf(nmTab + ".") > -1) {
						dlm32.removeElement(nmCpObj);
					}
				}
				//ștergem cp. tabelului din lista cu selecțiile de grupare :
			 	DefaultListModel dlm42 = (DefaultListModel) 
			 		groupCp2LSi2B.lista2.getModel();
				for (Object nmCpObj : dlm42.toArray()) {
					String nmCpStr = (String) nmCpObj;
					if (nmCpStr.indexOf(nmTab + ".") > -1) {
						dlm42.removeElement(nmCpObj);
					}
				}
				//ștergem  cp. tabelului din coloana Nume Camp din tabela where
				//și ștergem tot ce e scris în tabela where :
				for (int i = 0; i < wherePanel.numeCpCBoxModel.getSize(); i++) {
					Object nmCpObj = wherePanel.numeCpCBoxModel.getElementAt(i);
					String nmCpStr = (String) nmCpObj;
					if (nmCpStr.indexOf(nmTab + ".") > -1) {
						wherePanel.numeCpCBoxModel.removeElement(nmCpObj);
						i--;	//s-a eliminat un element
					}
				}
				for (int i = 0; i < wherePanel.criteriiTable.getRowCount(); i++){
					wherePanel.nivelImbricHash.put(new Integer(i), 
						new Integer(0));
					for (int j = 0; j < 8; j++)
						wherePanel.criteriiTable.setValueAt("", i, j);
				}
			}
		//deselectăm un câmp :	
			else if ((((JButton)e.getSource()).equals(selCp2LSi2B.buton2))) {
				if (selCp2LSi2B.lista2.isSelectionEmpty())
					return;
				String nmCp = (String) selCp2LSi2B.lista2.getSelectedValue();
				((DefaultListModel)selCp2LSi2B.lista2.getModel(
					)).removeElement(nmCp);
				//îl elimină, și din hashtable cu numele noi, dacă e acolo :
				String nmNou = numeNouCpHash.get(nmCp);
				if (nmNou != null)
					numeNouCpHash.remove(nmCp);
				numeNouCpTxFld.setText("");	//ștergem din textbox
				//ștergem din tabelul having
				for (int j = 0; j < 
					havingWherePanel.numeCpCBoxModel.getSize(); j++) {
					if (havingWherePanel.numeCpCBoxModel.getElementAt(
						j).toString().equals(nmCp) || 
						havingWherePanel.numeCpCBoxModel.getElementAt(
						j).toString().equals(nmNou))
						havingWherePanel.numeCpCBoxModel.removeElementAt(
							j);	
				}
				if (! existaFctAgregata())
					groupCp2LSi2B.buton1.setEnabled(false);
				
				
				//dacă e expr. sau fcț., va fi mai jos de expresie aritm. și
				//îl eliminăm din lista1 :
				selCp2LSi2B.lista1.setSelectedValue("expresie aritmetică",
					false);
				int idxExprAritm = selCp2LSi2B.lista1.getSelectedIndex();
				if (((DefaultListModel)selCp2LSi2B.lista1.getModel(
					)).contains(nmCp)) {
					selCp2LSi2B.lista1.setSelectedValue(nmCp, false);
					if (selCp2LSi2B.lista1.getSelectedIndex() > idxExprAritm)	
						((DefaultListModel)selCp2LSi2B.lista1.getModel(
							)).removeElement(nmCp);
				}
			}
		//selectăm un câmp pt. afișare
			else if (((JButton)e.getSource()).equals(selCp2LSi2B.buton1)) {
				if (selCp2LSi2B.lista1.isSelectionEmpty())
					return;
				String nmCp = (String) selCp2LSi2B.lista1.getSelectedValue();
				int ind = selCp2LSi2B.lista1.getSelectedIndex();
				Vector<String> listExclud = new Vector<String>();
				listExclud.addElement("expresie aritmetică");
				listExclud.addElement("SUM");
				listExclud.addElement("COUNT");
				listExclud.addElement("MIN");
				listExclud.addElement("MAX");
				listExclud.addElement("AVG");			
				DefaultListModel dlm21 = (DefaultListModel)
					selCp2LSi2B.lista1.getModel();
				DefaultListModel dlm22 = (DefaultListModel)			
					selCp2LSi2B.lista2.getModel();		
					//este câmp:
				if (ind > -1 && ind < dlm21.indexOf("expresie aritmetică") &&
					! dlm22.contains(nmCp)) {
					dlm22.addElement(nmCp);
					selCp2LSi2B.lista2.setSelectedValue(nmCp, true);
				}
				else if (nmCp.equals("SUM") || 
					nmCp.equals("expresie aritmetică")) {
					selCp2LSi2B.lista2.clearSelection();
					exprAritmLabel.setEnabled(true);
					exprAritmTxFld.setEnabled(true);
					exprAritmTxFld.requestFocusInWindow();
				}
				else if (nmCp.equals("COUNT") || nmCp.equals("MIN") ||
					nmCp.equals("MAX") || nmCp.equals("AVG")) {
					Vector<String> listArgFct = new Vector<String>();
					DefaultListModel dlm =  (DefaultListModel)
						selCp2LSi2B.lista1.getModel();
					for (int i = 0; i < dlm.getSize(); i++) {
						String selCp = (String)
							dlm.getElementAt(i);
						if (! listExclud.contains(selCp) && ! selCp.endsWith(
							".*"))
							listArgFct.addElement(selCp);
					}
					if (! nmCp.equals("COUNT")) {
						Object selCpObj = 	
						JOptionPane.showInputDialog(parinte,"Selectați câmpul "
						+ "la care se aplică funcția : ", "Decideți argumentul "
						+ "funcției", JOptionPane.QUESTION_MESSAGE, null,
						listArgFct.toArray(), null);
						nmCp = nmCp + "(" + selCpObj.toString() + ")";
					}
					else {		//este COUNT
						String argPtCount = "";
						ArgCountDialog dialog = new ArgCountDialog(parinte, 
						"Precizați argumentele funcției COUNT",true,listArgFct);
						nmCp = nmCp + "(" + dialog.listStr + ")";
					}
					if (! dlm.contains(nmCp))	
						dlm.addElement(nmCp);
					dlm = (DefaultListModel)
						selCp2LSi2B.lista2.getModel();
					if (! dlm.contains(nmCp))	
						dlm.addElement(nmCp);
					selCp2LSi2B.lista2.setSelectedValue(nmCp, true);
					numeNouCpTxFld.requestFocusInWindow();
					//dacă e o fcț. agregat, o adăugăm în havingWherePanel
					listExclud.removeElement("expresie aritmetică");
					for (String excStr : listExclud) {
						if (nmCp.indexOf(excStr + "(") > -1) {
							havingWherePanel.numeCpCBoxModel.addElement(nmCp);
						}
					}
				}
				numeNouCpTxFld.setText("");
				selCp2LSi2B.lista2.setSelectedValue(nmCp, true);
			}
		}
	}
	
	public class ArgCountDialog extends JDialog implements ActionListener {
		private JList argCountList;
		private JButton okButton;
		private Vector<String> listArgFct;
			String listStr = "";	//lista cu argumentele returnate
		public ArgCountDialog(JFrame parinte, String titlu, boolean modala,
			Vector<String> listArgFct) {
			super(parinte, titlu, modala);
			this.listArgFct = listArgFct;
			listArgFct.insertElementAt("*", 0);
			JPanel contPanel = new JPanel();
			contPanel.setOpaque(true);
			contPanel.setLayout(new BoxLayout(contPanel, BoxLayout.Y_AXIS));
			argCountList = new JList(new DefaultListModel());	//adaugă elemente
			argCountList.setLayoutOrientation(JList.VERTICAL);
			argCountList.setVisibleRowCount(-1);
			argCountList.setSelectionMode(
				ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);	
			JScrollPane listArgScrPane = new JScrollPane(argCountList);
			listArgScrPane.setPreferredSize(new Dimension(100, 130));
			listArgScrPane.setMaximumSize(new Dimension(120, 180));
			DefaultListModel dlm = (DefaultListModel)
				argCountList.getModel();
			for (String cpCrt : listArgFct)
				dlm.addElement(cpCrt);
			contPanel.add(argCountList);
			contPanel.add(Box.createVerticalStrut(10));
			okButton = new JButton("Închide");
			okButton.addActionListener(this);
			okButton.setAlignmentX(0.5f);
			contPanel.add(okButton);
			contPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15,15));
			setContentPane(contPanel);
			setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
			setDefaultLookAndFeelDecorated(true);
			pack();
			InterfataGrafica.centerFrameOnScreen (this);
			setVisible(true);
		}
		public void actionPerformed(ActionEvent e) {
			if (((JButton)e.getSource()).equals(okButton)){
				listStr = "";
				if (argCountList.isSelectionEmpty()){
					JOptionPane.showMessageDialog(this, "Trebuie precizat cel "
					+ "puțin un argument pentru funcția COUNT !", "Eroare !",
					JOptionPane.ERROR_MESSAGE);
					return;
				}
				DefaultListModel dlm = 
					(DefaultListModel)argCountList.getModel();
				int nrSel = dlm.getSize();
				int nrCpSel = 0;
				for (int i = 0; i < nrSel; i++)	
					if (argCountList.isSelectedIndex(i)) {
						listStr += dlm.getElementAt(i).toString() + ", ";						
						nrCpSel++;
					}
				if (! listStr.equals(""))
					listStr = listStr.substring(0, listStr.length() - 2);
				if (nrCpSel > 1) {
					listStr = "DISTINCT " + listStr;
				}	
				dispose();
			}
		}
	}
	
	public Interogare(InterfataGrafica interfataGrafica, String numeBazaDeDate) {
		super("Interogare Mysql. Select");
		this.interfataGrafica = interfataGrafica;
		this.numeBazaDeDate = numeBazaDeDate;
		numeNouCpHash = new Hashtable<String, String>();
//		tabeleHash = new Hashtable<String, TabelMysqlObj>(); 	
		//ascultă la butoanele selecției :	
		AscultaLaButSel ascButSel = new AscultaLaButSel(this);
		//ascultă la butoanele selecției pt order by și group by :	
		AscLaButOrdSiAgreg ascButOrdSiAgreg = new AscLaButOrdSiAgreg();
		editManPanel = new EditManualPanel();
		editManPanel.editManButton.addActionListener(this);
		//creăm panelul cu selecția pt. tabele și câmpuri
		selTab2LSi2B = new DouaListeSiButoanePattern();
		selTab2LSi2B.buton1.addActionListener(ascButSel);
		selTab2LSi2B.buton2.addActionListener(ascButSel);
		//ascultă la modificarea componentelor listelor din 2LSi2B cu tabele
		AscultaLaModifLista ascModListTab = new AscultaLaModifLista(
			selTab2LSi2B);
		selTab2LSi2B.lista1.getModel().addListDataListener(ascModListTab);
		selTab2LSi2B.lista2.getModel().addListDataListener(ascModListTab);
		selCp2LSi2B = new DouaListeSiButoanePattern();
		selCp2LSi2B.buton1.addActionListener(ascButSel);
		selCp2LSi2B.buton2.addActionListener(ascButSel);
		//ascultă la modificarea componentelor listelor din 2LSi2B cu cp.
		AscultaLaModifLista ascModListCp = new AscultaLaModifLista(selCp2LSi2B);
		selCp2LSi2B.lista1.getModel().addListDataListener(ascModListCp);
		DefaultListModel dlm = (DefaultListModel) selCp2LSi2B.lista1.getModel();
		dlm.addElement("expresie aritmetică");
		dlm.addElement("SUM");
		dlm.addElement("COUNT");
		dlm.addElement("MIN");
		dlm.addElement("MAX");
		dlm.addElement("AVG");
		
		selCp2LSi2B.lista2.getModel().addListDataListener(ascModListCp);
		selCp2LSi2B.lista2.addMouseListener(this);
		JPanel tabPanel = new JPanel(new BorderLayout());
		tabPanel.setOpaque(true);
		tabPanel.add(selTab2LSi2B, BorderLayout.CENTER);
		tabPanel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createCompoundBorder(
				BorderFactory.createEmptyBorder(0, 0, 5, 0),
				BorderFactory.createTitledBorder("Selectați tabelele")), 
			BorderFactory.createEmptyBorder(3, 6, 6, 6))); 
		JPanel cpPanel = new JPanel(new BorderLayout());
		cpPanel.setOpaque(true);
		cpPanel.add(selCp2LSi2B, BorderLayout.CENTER);
		cpPanel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createCompoundBorder(
				BorderFactory.createEmptyBorder(2, 0, 5, 0),
				BorderFactory.createTitledBorder("Selectați câmpurile")), 
			BorderFactory.createEmptyBorder(3, 6, 4, 6)));
		JPanel selPanel = new JPanel();
		selPanel.setOpaque(true);
		selPanel.setLayout(new BoxLayout(selPanel, BoxLayout.X_AXIS));
		selPanel.add(Box.createHorizontalStrut(5));
		selPanel.add(tabPanel);
		selPanel.add(Box.createHorizontalStrut(20));
		selPanel.add(Box.createHorizontalGlue());
		selPanel.add(cpPanel);
		selPanel.add(Box.createHorizontalStrut(5));
		JPanel selValidPanel = new JPanel();
		selValidPanel.setLayout(new BorderLayout());
		selValidPanel.setOpaque(true);
		selValidPanel.add(selPanel, BorderLayout.CENTER);
		JPanel exSiButPanel = new JPanel();
		exSiButPanel.setLayout(new BoxLayout(exSiButPanel, BoxLayout.X_AXIS));
		//textfield cu expresia aritmetică
		exprAritmLabel = new JLabel("Expr. aritmetică : ", JLabel.LEFT);
		exprAritmTxFld = new JTextField();
		exprAritmTxFld.setPreferredSize(new Dimension(200, 20));
		exprAritmTxFld.setMaximumSize(new Dimension(230, 20));
		exprAritmTxFld.setEnabled(false);
		exprAritmTxFld.setInputVerifier(new ExprAritmVerifier(this, -1, -1));
		exprAritmLabel.setLabelFor(exprAritmTxFld);
		exprAritmLabel.setDisplayedMnemonic(KeyEvent.VK_P);
		exprAritmLabel.setEnabled(false);
		Font simpluFont = exprAritmTxFld.getFont().deriveFont(Font.PLAIN, 11);
		exprAritmTxFld.setFont(simpluFont);
		//textfield cu nume nou pentru câmpuri selectate :
		numeNouCpLabel = new JLabel("Nume nou câmp : ", JLabel.LEFT);
		numeNouCpTxFld = new JTextField();
		numeNouCpTxFld.setMaximumSize(new Dimension(110, 20));
		numeNouCpTxFld.setPreferredSize(new Dimension(90, 20));
		numeNouCpTxFld.setToolTipText(
			"Scrieți noul nume sub care se va afișa câmpul și apăsați <enter>");
		numeNouCpTxFld.setActionCommand("nume nou");
		numeNouCpTxFld.addActionListener(new AscultaLaText());
		numeNouCpLabel.setLabelFor(numeNouCpTxFld);
		numeNouCpLabel.setDisplayedMnemonic(KeyEvent.VK_N);
		distinctCheckBox = new JCheckBox("Rânduri distincte");
		distinctCheckBox.setMnemonic(KeyEvent.VK_R);
		distinctCheckBox.setToolTipText("Rândurile duplicat se afișează "
		+ "o singură dată");
		exSiButPanel.add(Box.createHorizontalStrut(8));
		exSiButPanel.add(distinctCheckBox);
		exSiButPanel.add(Box.createHorizontalStrut(20));
		exSiButPanel.add(Box.createHorizontalGlue());
		exSiButPanel.add(exprAritmLabel);
		exSiButPanel.add(exprAritmTxFld);
		exSiButPanel.add(Box.createHorizontalStrut(20));
		exSiButPanel.add(Box.createHorizontalGlue());
		exSiButPanel.add(numeNouCpLabel);
		exSiButPanel.add(numeNouCpTxFld);
		exSiButPanel.add(Box.createHorizontalStrut(8));
		selValidPanel.add(exSiButPanel, BorderLayout.SOUTH);
		//componentele din clauza order by :
		orderCp2LSi2B = new DouaListeSiButoanePattern();
		orderCp2LSi2B.buton1.addActionListener(ascButOrdSiAgreg);
		orderCp2LSi2B.buton2.addActionListener(ascButOrdSiAgreg);
		//preluăm cp. din selCp, lista1 :
		orderCp2LSi2B.lista1.setModel(selCp2LSi2B.lista1.getModel());
		//ascultă la modificarea componentelor listelor din 2LSi2B cu cp.
		AscultaLaModifLista ascModListOrderCp = new AscultaLaModifLista(
			orderCp2LSi2B);
		orderCp2LSi2B.lista1.getModel().addListDataListener(ascModListOrderCp);
		orderCp2LSi2B.lista2.getModel().addListDataListener(ascModListOrderCp);
		orderAscRadioButton = new JRadioButton("Ordonare ascendentă", true);
		orderAscRadioButton.setMnemonic(KeyEvent.VK_A);
		orderDescRadioButton = new JRadioButton("Ordonare descendentă");
		orderDescRadioButton.setMnemonic(KeyEvent.VK_D);
		ButtonGroup ordonBG = new ButtonGroup();
		ordonBG.add(orderAscRadioButton);
		ordonBG.add(orderDescRadioButton);
		JLabel limitLabel = new JLabel("Limitează rezultat : ", JLabel.LEFT);
		limitTxField = new JTextField();
		limitTxField.setMaximumSize(new Dimension(110, 20));
		limitTxField.setPreferredSize(new Dimension(90, 20));
		limitTxField.setToolTipText(
			"Un nr. întreg : câte rânduri va afișa. Două nr. întregi despărțite"
			+ " de virgulă : ofsetul și respectiv nr. de rânduri afișate");
		limitLabel.setLabelFor(limitTxField);
		limitLabel.setDisplayedMnemonic(KeyEvent.VK_L);
		validOrderButton = new JButton("Validează");
		validOrderButton.setMnemonic(KeyEvent.VK_V);
		validOrderButton.addActionListener(this);
		//panelul cu tip ordonare :
		JPanel ascDescPanel = new JPanel();
		ascDescPanel.setOpaque(true);
		ascDescPanel.setLayout(new BoxLayout(ascDescPanel, BoxLayout.Y_AXIS));
		ascDescPanel.add(orderAscRadioButton);
		ascDescPanel.add(orderDescRadioButton);
		ascDescPanel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createTitledBorder("Tip ordonare"), 
			BorderFactory.createEmptyBorder(6, 6, 6, 6))); 
		//panelul cu câmpurile de ordonare și cu tipul ei :
		JPanel ordTipPanel = new JPanel();
		ordTipPanel.setOpaque(true);
		ordTipPanel.setLayout(new BoxLayout(ordTipPanel, BoxLayout.X_AXIS));
		ordTipPanel.add(orderCp2LSi2B);
		ordTipPanel.add(Box.createHorizontalStrut(20));
		ordTipPanel.add(Box.createHorizontalGlue());
		ordTipPanel.add(ascDescPanel);
		ordTipPanel.add(Box.createHorizontalStrut(30));
		//panelul cu limit și but. de afișare comanda :
		JPanel limitPanel = new JPanel();
		limitPanel.setOpaque(true);
		limitPanel.setLayout(new BoxLayout(limitPanel, BoxLayout.X_AXIS));
		limitPanel.add(Box.createHorizontalStrut(30));
		limitPanel.add(limitLabel);
		limitPanel.add(limitTxField);
		limitPanel.add(Box.createHorizontalStrut(70));
		limitPanel.add(Box.createHorizontalGlue());
		limitPanel.add(validOrderButton);
		limitPanel.add(Box.createHorizontalStrut(30));
		//panelul cu clauza order by :
		JPanel orderPanel = new JPanel();
		orderPanel.setOpaque(true);
		orderPanel.setLayout(new BoxLayout(orderPanel, BoxLayout.Y_AXIS));
		orderPanel.add(Box.createVerticalStrut(10));
		orderPanel.add(ordTipPanel);
		orderPanel.add(Box.createVerticalStrut(30));
		orderPanel.add(Box.createHorizontalGlue());
		orderPanel.add(limitPanel);
		orderPanel.add(Box.createVerticalStrut(10));
		//Formăm selecția pt. GROUP BY:
		groupCp2LSi2B = new DouaListeSiButoanePattern();
		groupCp2LSi2B.buton1.setEnabled(false);
		groupCp2LSi2B.buton1.addActionListener(ascButOrdSiAgreg);
		groupCp2LSi2B.buton2.addActionListener(ascButOrdSiAgreg);
		//preluăm cp. din selCp, lista1 :
		groupCp2LSi2B.lista1.setModel(selCp2LSi2B.lista1.getModel());
		//ascultă la modificarea componentelor listelor din 2LSi2B cu cp.
		AscultaLaModifLista ascModListGroupCp = new AscultaLaModifLista(
			groupCp2LSi2B);
		groupCp2LSi2B.lista1.getModel().addListDataListener(ascModListGroupCp);
		groupCp2LSi2B.lista2.getModel().addListDataListener(ascModListGroupCp);
		//ASC / DESC pt. GROUP BY
		groupAscRadioButton = new JRadioButton("Grupare ascendentă");
		groupAscRadioButton.setMnemonic(KeyEvent.VK_A);
		groupAscRadioButton.setSelected(true);
		groupDescRadioButton = new JRadioButton("Grupare descendentă");
		groupDescRadioButton.setMnemonic(KeyEvent.VK_D);
		ButtonGroup groupBG = new ButtonGroup();
		groupBG.add(groupAscRadioButton);
		groupBG.add(groupDescRadioButton);
		//butonul de afisare la GROUP BY
		validGroupButton = new JButton("Validează");
		validGroupButton.setMnemonic(KeyEvent.VK_V);
		validGroupButton.addActionListener(this);
		//panelul cu tip grupare (asc sau desc):
		JPanel ascDescGroupPanel = new JPanel();
		ascDescGroupPanel.setOpaque(true);
		ascDescGroupPanel.setLayout(new BoxLayout(
			ascDescGroupPanel, BoxLayout.Y_AXIS));
		ascDescGroupPanel.add(groupAscRadioButton);
		ascDescGroupPanel.add(groupDescRadioButton);
		ascDescGroupPanel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createTitledBorder("Tip grupare"), 
			BorderFactory.createEmptyBorder(6, 6, 6, 6))); 
		
		//Panelul cu asc/desc și butonul
		JPanel ascDescButPanel = new JPanel();
		ascDescButPanel.setLayout(new BoxLayout(
			ascDescButPanel, BoxLayout.Y_AXIS));
		ascDescButPanel.add(ascDescGroupPanel);
		ascDescButPanel.add(Box.createVerticalStrut(60));
		ascDescButPanel.add(validGroupButton);
		//Panelul pt liste 
		JPanel listGroupPanel = new JPanel();
		listGroupPanel.setLayout(new BoxLayout(
			listGroupPanel, BoxLayout.Y_AXIS));
		listGroupPanel.add(Box.createVerticalStrut(45));
		listGroupPanel.add(groupCp2LSi2B);
		//Panelul pt. GROUP BY:
		JPanel groupPanel = new JPanel();
		groupPanel.setOpaque(true);
		groupPanel.setLayout(new BoxLayout(groupPanel, BoxLayout.X_AXIS));
		groupPanel.add(listGroupPanel);
		groupPanel.add(Box.createHorizontalStrut(20));
		groupPanel.add(Box.createHorizontalGlue());
		groupPanel.add(ascDescButPanel);
		groupPanel.add(Box.createHorizontalStrut(30));
		
		//Panelul clauzei HAVING
		havingWherePanel = new WherePanel(this, false);
		havingWherePanel.numeCpCBoxModel = new DefaultComboBoxModel(
			havingWherePanel.nulArray);
		havingWherePanel.numeCpCBoxModel.insertElementAt("expresie aritmetică", 0);
		JPanel havingPanel = new JPanel();
		havingPanel.setOpaque(true);
		havingPanel.add(havingWherePanel);
		//panelul cu join
		joinPanel = new JoinPanel();
		//TabbedPane ce va conține clauzele where, order by, group by
		criteriiTabbedPane = new JTabbedPane();
		wherePanel = new WherePanel(this, true);
		criteriiTabbedPane.addTab("Clauza Where", wherePanel);
		criteriiTabbedPane.addTab("Clauza Join", joinPanel);
		criteriiTabbedPane.addTab("Clauza Group By", groupPanel);
		criteriiTabbedPane.addTab("Clauza Having", havingPanel);
		criteriiTabbedPane.addTab("Clauza Order By", orderPanel);
		criteriiTabbedPane.addChangeListener(this);

		//Crează panelul cu butoanele finale ale tabelului
		JPanel butonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 50, 10));
		selectButton = new JButton("Execută SELECT");
		selectButton.setMnemonic(KeyEvent.VK_S);
		selectButton.addActionListener(this);
		inchidButton = new JButton("Închidere");
		inchidButton.setMnemonic(KeyEvent.VK_N);
		inchidButton.addActionListener(this);
		butonPanel.add(inchidButton);
		butonPanel.add(selectButton);


		JPanel reuniunePanel = new JPanel();
		reuniunePanel.setOpaque(true);
		reuniunePanel.setLayout(new BoxLayout(reuniunePanel, BoxLayout.Y_AXIS));
		reuniunePanel.add(editManPanel);
		reuniunePanel.add(selValidPanel);
		reuniunePanel.add(criteriiTabbedPane);
		reuniunePanel.add(butonPanel);
		
		setContentPane(reuniunePanel);
		//populăm lista de tabele cu tab. din bd :
		File bddDir = new File(numeBazaDeDate);
		if (bddDir.exists() && bddDir.isDirectory()) {
			String[] fisStr = bddDir.list();	//listează directorul bază de date
			for (String crtFisStr : fisStr) {
				int ind = crtFisStr.lastIndexOf(".txt");
				crtFisStr = crtFisStr.substring(0, ind);
				((DefaultListModel)selTab2LSi2B.lista1.getModel(
					)).addElement(crtFisStr);
			}
		}
	}
	//la selecția unui câmp, dacă are un nume nou, se va afișa în numeNouCpTxFld
	public void valueChanged(ListSelectionEvent e) {
		numeNouCpTxFld.setText("");
		Object numeNouObj;
		if ((numeNouObj = numeNouCpHash.get(
			selCp2LSi2B.lista2.getSelectedValue())) != null) {
				String nmNouStr = numeNouObj.toString();
				numeNouCpTxFld.setText(nmNouStr);
				numeNouCpTxFld.selectAll();
				numeNouCpTxFld.requestFocusInWindow();
		}
	}
	
	public void mouseEntered(MouseEvent e) {
		if (e.getSource() == selCp2LSi2B.lista2) {
			selCp2LSi2B.lista2.addListSelectionListener(this);
		}
	}
	public void mouseExited(MouseEvent e) { 
		if (e.getSource() == selCp2LSi2B.lista2) {
			selCp2LSi2B.lista2.removeListSelectionListener(this);
		}
	}
	public void mouseClicked(MouseEvent e) {} 
	public void mousePressed(MouseEvent e) {} 
	public void mouseReleased(MouseEvent e) {} 

	//când de face clic pe un tab din criteriiTabbedPane
	public void stateChanged(ChangeEvent e) {
		wherePanel.compuneClauzaWhere();
		joinPanel.formareJoin();
		formareGroup();
		havingWherePanel.compuneClauzaWhere();
		formareOrder();
		formareComanda();
	}
	
	public void itemStateChanged(ItemEvent e) {
		if (((JCheckBox) e.getSource()) == distinctCheckBox) {
			formareSelect();
			formareComanda();	
		}
	}
	
	public void actionPerformed(ActionEvent e) {
		JButton src = (JButton) e.getSource();
		if (src == inchidButton) {
			dispose();
		}
		else if (src == editManPanel.editManButton) {
			Toolkit.getDefaultToolkit().beep();
			int answ = JOptionPane.showConfirmDialog(this, 
				"Dacă decideți să editați comanda MYSQL, pierdeți suportul" +
				" oferit de interfața grafică.\nEditați comanda?", "Întrebare",
				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
			if (answ == JOptionPane.YES_OPTION) {
				criteriiTabbedPane.setSelectedIndex(0);
				JComponent[] compArray = {editManPanel.editManButton, 
				selTab2LSi2B.lista1, selTab2LSi2B.lista2, selTab2LSi2B.buton1,
				selTab2LSi2B.buton2, selCp2LSi2B.lista1, selCp2LSi2B.lista2,
				selCp2LSi2B.buton1,	selCp2LSi2B.buton2,	distinctCheckBox, 
				exprAritmLabel, exprAritmTxFld, numeNouCpLabel, numeNouCpTxFld,
				wherePanel.criteriiTable, wherePanel.exprAritmLabel, 
				wherePanel.exprAritmTxFld, wherePanel.validButton};
				for (JComponent compon : compArray) 
					compon.setEnabled(false);
				formareComanda();
				criteriiTabbedPane.setEnabled(false);
				editManPanel.comandaEditorPane.setEditable(true);
				editManPanel.comandaEditorPane.setContentType("text/plain");
				editManPanel.comandaEditorPane.setText(comandaString.toString());
				editManPanel.comandaEditorPane.requestFocusInWindow();
				
			}
		}
		else if (src == validOrderButton) { //butonul order by
			formareOrder();
			formareComanda();	
		}
		else if (src == validGroupButton) { //butonul group by
			formareGroup();
			formareComanda();	
		}
		else if (src == selectButton) {
			DefaultListModel dlm = (DefaultListModel)
				selCp2LSi2B.lista2.getModel();
			if (dlm.isEmpty()) {
				JOptionPane.showMessageDialog(this, "Trebuie să existe un câmp "
					+ "selectat", "Eroare", JOptionPane.ERROR_MESSAGE);
				selCp2LSi2B.buton1.requestFocusInWindow();
				return;
			}
			if (existaFctAgregata() && ((DefaultListModel)
				groupCp2LSi2B.lista2.getModel()).isEmpty()) {
				JOptionPane.showMessageDialog(this, "Există funcție agregată !"
					+ "\nLista de grupare nu poate fi vidă !", "Eroare", 
					JOptionPane.ERROR_MESSAGE);
				criteriiTabbedPane.setSelectedIndex(2);
				groupCp2LSi2B.buton1.requestFocusInWindow();
				return;
			}
			formareSelect();
			joinPanel.validButton.doClick();
			wherePanel.validButton.doClick();
			formareGroup();
			havingWherePanel.validButton.doClick();
			formareOrder();
			formareComanda();
			if (wherePanel.eroareSintaxa || havingWherePanel.eroareSintaxa ||
				joinPanel.eroareSintaxa)
				return;
			//executăm comanda SELECT:

			ResultSet rez;
			// aducem toate înregistrările din tabel :
			try {
				Statement s_ment = interfataGrafica.conex.createStatement(
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_READ_ONLY);
				rez = s_ment.executeQuery(comandaString.toString());
			}
			catch (SQLException exc) {
				JOptionPane.showMessageDialog(null, "Nu s-a putut executa "
			 	+ " interogarea MySQL !\n" + 
			 	exc.getMessage(), "Atenție ! Eroare !", JOptionPane.ERROR_MESSAGE);
				return;
			}
			int nrTotRand = 0;
			try {
			    rez.last();                   
		      	nrTotRand = rez.getRow();
			}
			catch (SQLException exc) {
				exc.getMessage();
				return;
			}
			if (nrTotRand == 0) {
				JOptionPane.showMessageDialog(null, 
				 	"Interogarea MySQL a returnat\nzero înregistrări !", 
				 	"Atenție !", JOptionPane.WARNING_MESSAGE);
				return;
			}
			else {
				TabelOperatii tabOp = new TabelOperatii(interfataGrafica, 
					comandaString.toString(), rez);
				tabOp.pack();
				tabOp.deleteButton.setVisible(false);
				tabOp.insertButton.setVisible(false);
				tabOp.viewTable.setEnabled(false);
				dispose();
				interfataGrafica.centerFrameOnScreen (tabOp);
				tabOp.setVisible(true);
			}
		}
	}
	
	//partea din comandă : select  
	public void formareSelect() {
		selString = new StringBuffer("SELECT ");
		selHtmlString = new StringBuffer("SELECT ");
	 	if (distinctCheckBox.isSelected()) {
	 		selString = selString.append("DISTINCT ");
			selHtmlString = selHtmlString.append("<font color=\"blue\">" +
				"DISTINCT " + "</font>");
	 	}
	 	selHtmlString = selHtmlString.append("<font color=\"red\">");
	 	DefaultListModel dlm22 = (DefaultListModel)
			selCp2LSi2B.lista2.getModel();
		Object[] selCpArray = dlm22.toArray();
		for (int i = 0; i < selCpArray.length; i++) {
			String selCpCrtStr = selCpArray[i].toString();
			selString = selString.append(selCpCrtStr);
			selHtmlString = selHtmlString.append(selCpCrtStr);
			String nmNouStr = numeNouCpHash.get(selCpCrtStr);
			if (nmNouStr != null) {	//are clauza AS
				selString = selString.append(" AS " + nmNouStr);
				selHtmlString = selHtmlString.append("</font><font color=\"blue\">" +
					" AS " + "</font><font color=\"green\">" + nmNouStr
					+ "</font><font color=\"red\">");
			}
			selString = selString.append(i < selCpArray.length - 1 ? ", " : "");
			selHtmlString = selHtmlString.append(i < selCpArray.length - 1 ? 
				", " : "");
		}
		selHtmlString = selHtmlString.append("</font>");
	 	//pt. cazul când clauza FROM când avem un singur tabel
	 	DefaultListModel dlm12 = (DefaultListModel)
			selTab2LSi2B.lista2.getModel();
		if (dlm12.isEmpty())
			return;
		else if (dlm12.getSize() == 1) {
			selString = selString.append(" FROM ");	
			selHtmlString = selHtmlString.append(" FROM ");	
			String nmTab = (String) dlm12.getElementAt(0);
			selString = selString.append(nmTab);
			selHtmlString = selHtmlString.append("<font color=\"red\">" +
				nmTab + "</font>");
		}
	}
	
	
	
	public void formareOrder() {
		//verificăm dacă clauza limit apare bine în limitTxField
		String limitStr = limitTxField.getText();
		int index;
		boolean corect = true;
		if ((index = limitStr.indexOf(",")) > 0) {
			int n1, n2;
			try {
				String trimStr = limitStr.substring(0, index).trim();
				n1 = Integer.parseInt(trimStr);
				trimStr = limitStr.substring(index + 1).trim();
				n2 = Integer.parseInt(trimStr);
				if (n1 < 0 || n2 < 0)
					corect = false;
			}
			catch (NumberFormatException exc) {
				corect = false;
			}	
		}
		else {
			try {
				int n1 = Integer.parseInt(limitStr);
				if (n1 < 0)
					corect = false;
			}
			catch (NumberFormatException exc) {
				corect = false;
			}	
		}
		if (! corect && ! limitTxField.getText().equals("")) {
			JOptionPane.showMessageDialog(this, "Introduceți un întreg pozitiv " +
				"(numărul de înregistrări afișate)\n sau doi întregi pozitivi"
				+ " despărțiți prin virgulă\n (offsetul și respectiv " +
				"numărul de înregistrări afișate)", "Eroare", 
		 		JOptionPane.ERROR_MESSAGE);
		 	limitTxField.setText("");
		 	limitTxField.requestFocusInWindow();
		}
		//construim clauzele order by și limit
		DefaultListModel dlm = (DefaultListModel)
			orderCp2LSi2B.lista2.getModel();
		String listCpDeOrdString;
		orderString = new StringBuffer("");
		orderHtmlString = new StringBuffer("");
		if (! dlm.isEmpty()){	//avem cp. de ordonare
			listCpDeOrdString = dlm.getElementAt(0).toString();
			for (int i = 1; i < dlm.size(); i++)
				listCpDeOrdString += ", " + dlm.getElementAt(i);
			orderString = new StringBuffer(" ORDER BY " + listCpDeOrdString);
			orderHtmlString = new StringBuffer(" ORDER BY <font color=" +
				"\"red\">" + listCpDeOrdString + "</font>");
			if (orderDescRadioButton.isSelected()) {
				orderString = orderString.append(" DESC");
				orderHtmlString = orderHtmlString.append("<font color=" +
				"\"blue\">" + " DESC</font>");
			}
		}
		if (! limitTxField.getText().equals("")) {
			orderString = orderString.append(" LIMIT " +
				limitTxField.getText());
			orderHtmlString = orderHtmlString.append(" LIMIT <font color=" +
				"\"green\">" + limitTxField.getText() + "</font>");
		}
	}
	
	public void formareGroup() {
		DefaultListModel dlm = (DefaultListModel)
			groupCp2LSi2B.lista2.getModel();
		String listCpDeGroupString = "";
		groupString = new StringBuffer("");
		groupHtmlString = new StringBuffer("");
		if (dlm.isEmpty()) {
			return;
		}
		else {	//avem cp. de ordonare
			listCpDeGroupString = dlm.getElementAt(0).toString();
			for (int i = 1; i < dlm.size(); i++)
				listCpDeGroupString += ", " + dlm.getElementAt(i);
			groupString = groupString.append(" GROUP BY " + listCpDeGroupString);
			groupHtmlString = groupHtmlString.append(" GROUP BY <font color=" +
				"\"red\">" + listCpDeGroupString + "</font>");
			if (groupDescRadioButton.isSelected()) {
				groupString = groupString.append(" DESC");
				groupHtmlString = groupHtmlString.append("<font color=" +
				"\"blue\">" + " DESC</font>");
			}
		}
	}
	
	public void formareComanda() {
		comandaString = new StringBuffer();
		comandaHtmlString = new StringBuffer();
		comandaString = comandaString.append(selString.toString()).append(
			joinPanel.joinString.toString()).append(
			wherePanel.whereString.toString()
			).append(groupString.toString()).append(
			havingWherePanel.whereString.toString()).append(
			orderString.toString());
		comandaHtmlString = comandaHtmlString.append(selHtmlString.toString()
			).append(joinPanel.joinHtmlString.toString()).append(
			wherePanel.whereHtmlString.toString()).append(
			groupHtmlString.toString()
			).append(havingWherePanel.whereHtmlString.toString()
			).append(orderHtmlString.toString());
		editManPanel.comandaEditorPane.setText(comandaHtmlString.toString());
	}
	
	public boolean existaFctAgregata() {
	 	DefaultListModel dlm22 = (DefaultListModel)
			selCp2LSi2B.lista2.getModel();
		for (Object nmCpObj : dlm22.toArray()) {
			String nmCpStr = (String) nmCpObj;
			if (nmCpStr.startsWith("SUM(") || nmCpStr.startsWith("COUNT(") || 
				nmCpStr.startsWith("MIN(") || nmCpStr.startsWith("MAX(") || 
				nmCpStr.startsWith("AVG("))
				return true;
		}
		return false;
	}
	
	class JoinPanel extends JPanel implements ItemListener,  
		ActionListener, ListSelectionListener {
		JTable joinTable;
		StringBuffer joinString = new StringBuffer(""), 
			joinHtmlString = new StringBuffer(""); 
		String[] tipJoinArray = {"", "INNER JOIN", "LEFT JOIN", "JOIN"}; 
		DefaultComboBoxModel tab1CBoxModel, tab2CBoxModel, cpTab1CBoxModel, 
			cpTab2CBoxModel, tipJoinCBoxModel;
		JComboBox tab1CBox, tab2CBox, cpTab1CBox, cpTab2CBox, tipJoinCBox;
		JButton validButton;
		JLabel infoLabel;
		boolean eroareSintaxa = false;
	
		
		public JoinPanel() {
			super();
			setOpaque(true);
			setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
			String[] colNumeArray = {"Tabel 1", "Câmp în Tabel 1", "Tip Join", 
				"Tabel 2", "Câmp în Tabel 1"};
			//inițializăm tabelul cu șirul "" :
			String[][] date = new String[1][5];
			for (int j = 0; j < 5; j++)
				date[0][j] = "";
			joinTable = new JTable(new DefaultTableModel(date, colNumeArray));
			joinTable.setBackground(new Color(245, 245, 220));
			joinTable.setToolTipText("Pentru a edita o celulă, faceți dublu "
				+ "clic pe ea");
			//se va putea selecta un singur rând din tabel :
			joinTable.getSelectionModel().setSelectionMode(
				ListSelectionModel.SINGLE_SELECTION);
			//la fiecare selecție de rând combobox-urile trebuie să aibă val. specifice
			joinTable.getSelectionModel().addListSelectionListener(this);
			joinTable.setAlignmentY(0f);
			String[] nulArray = {""};
			joinTable.setPreferredScrollableViewportSize(new Dimension(
				650, 300));
			joinTable.setMinimumSize(new Dimension(650, 300));
			joinTable.setMaximumSize(new Dimension(750, 300));
			JScrollPane scrollPane = new JScrollPane(joinTable);
			//pt. coloana cu Tabel 1
			TableColumn crtColumn = joinTable.getColumnModel().getColumn(0);
			tab1CBoxModel = new DefaultComboBoxModel(nulArray);
			tab1CBox = new JComboBox(tab1CBoxModel);
			Font simpluFont = tab1CBox.getFont().deriveFont(Font.PLAIN, 10);
			tab1CBox.setFont(simpluFont);
			tab1CBox.addItemListener(this);
			crtColumn.setCellEditor(new DefaultCellEditor(tab1CBox));
			crtColumn.setMinWidth(70);
			((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
			//pt. coloana cu Câmp în Tabel 1
			crtColumn = joinTable.getColumnModel().getColumn(1);
			cpTab1CBoxModel = new DefaultComboBoxModel(nulArray);
			cpTab1CBox = new JComboBox(cpTab1CBoxModel);
			cpTab1CBox.setFont(simpluFont);
			cpTab1CBox.addItemListener(this);
			crtColumn.setCellEditor(new DefaultCellEditor(cpTab1CBox));
			crtColumn.setMinWidth(130);
			((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
			//pt. coloana cu Tip Join
			crtColumn = joinTable.getColumnModel().getColumn(2);
			tipJoinCBoxModel = new DefaultComboBoxModel(tipJoinArray);
			tipJoinCBox = new JComboBox(tipJoinCBoxModel);
			tipJoinCBox.setFont(simpluFont);
			tipJoinCBox.addItemListener(this);
			crtColumn.setCellEditor(new DefaultCellEditor(tipJoinCBox));
			crtColumn.setMinWidth(60);
			((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
			//pt. coloana cu Tabel 2
			crtColumn = joinTable.getColumnModel().getColumn(3);
			tab2CBoxModel = new DefaultComboBoxModel(nulArray);
			tab2CBox = new JComboBox(tab2CBoxModel);
			tab2CBox.setFont(simpluFont);
			tab2CBox.addItemListener(this);
			crtColumn.setCellEditor(new DefaultCellEditor(tab2CBox));
			crtColumn.setMinWidth(70);
			((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
			//pt. coloana cu Câmp în Tabel 2
			crtColumn = joinTable.getColumnModel().getColumn(4);
			cpTab2CBoxModel = new DefaultComboBoxModel(nulArray);
			cpTab2CBox = new JComboBox(cpTab2CBoxModel);
			cpTab2CBox.setFont(simpluFont);
			cpTab2CBox.addItemListener(this);
			crtColumn.setCellEditor(new DefaultCellEditor(cpTab2CBox));
			crtColumn.setMinWidth(130);
			((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
			//Eticheta și panelul cu info.
			JPanel infoPanel = new JPanel();
			infoPanel.setOpaque(true);
			infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
			infoLabel = new JLabel();
			infoLabel.setFont(simpluFont);
			infoLabel.setForeground(Color.magenta);
			infoLabel.setAlignmentY(0f);
			infoPanel.add(infoLabel);
			infoPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
			JScrollPane infoScrPane = new JScrollPane(infoPanel);
			infoScrPane.setPreferredSize(new Dimension(100, 150));
			infoScrPane.setAlignmentX(1f);
			infoScrPane.setMaximumSize(new Dimension(120, 150));
			//butonul cu afișarea
			validButton = new JButton("Validează");
			validButton.addActionListener(this);
			validButton.setMnemonic(KeyEvent.VK_V);
			validButton.setSize(40, 20);
			validButton.setAlignmentX(1f);
			//panelul cu tabelul
			JPanel tabPanel = new JPanel();
			tabPanel.setOpaque(true);
			tabPanel.setLayout(new BoxLayout(tabPanel, BoxLayout.Y_AXIS));
			tabPanel.add(scrollPane);
			tabPanel.setAlignmentY(0f);
			//panelul cu info și butonul
			JPanel infoButPanel = new JPanel();
			infoButPanel.setOpaque(true);
			infoButPanel.setLayout(new BoxLayout(infoButPanel, BoxLayout.Y_AXIS));
			infoButPanel.add(infoScrPane);
			infoButPanel.add(Box.createVerticalStrut(20));
			infoButPanel.add(validButton);
			infoButPanel.setAlignmentY(0f);
			add(tabPanel);
			add(Box.createHorizontalStrut(30));
			add(infoButPanel);
			setBorder(BorderFactory.createEmptyBorder(15, 15, 
				15, 15));
		}
	
		//umple cpTab1CBoxModel și cpTab2CBoxModel, coresp. numelui tabelului
		public void umpleListCp (int nrRand, String nmTab, boolean primulTabel) {
			int coloana = primulTabel ? 0 : 3;
			if (nmTab == null)
				nmTab = "";
			if (primulTabel) {
				cpTab1CBoxModel.removeAllElements();
				cpTab1CBoxModel.addElement("");
			}
			else {
				cpTab2CBoxModel.removeAllElements();
				cpTab2CBoxModel.addElement("");
			}
			//cp. le luăm din wherePanel, din numeCpCBoxModel
			for (int i = 0; i < wherePanel.numeCpCBoxModel.getSize(); i++) {
				String nmCpCrt = wherePanel.numeCpCBoxModel.getElementAt(i
					).toString();
				if (nmCpCrt.equals("expresie aritmetică"))
					break;		//mai jos sunt doar expr. aritm.
				if (nmCpCrt.startsWith(nmTab + ".")) {
					if (primulTabel)
						cpTab1CBoxModel.addElement(nmCpCrt);
					else 
						cpTab2CBoxModel.addElement(nmCpCrt);
				}
			}
		}
		
		public void actionPerformed(ActionEvent e) {
			eroareSintaxa = false;
			int nrTotRand = ((DefaultTableModel) joinTable.getModel(
				)).getRowCount();
			if (((DefaultListModel)selTab2LSi2B.lista2.getModel()).getSize() 
				< 2) return;
			for (int i = 0; i < nrTotRand; i++) {
				for (int j = 0; j < 5; j++) {
					if (joinTable.getValueAt(i, j).toString().equals("")) {
						JOptionPane.showMessageDialog(this, "Nu trebuie să " +
							"existe\n celule libere în tabelul JOIN!", "Eroare", 
							JOptionPane.ERROR_MESSAGE);
						criteriiTabbedPane.setSelectedIndex(1);
						eroareSintaxa = true;
						return;
					}
				}
//tab1 trebuie să fie unul din tabelele din susul tabelului join, iar tab2 
//să nu mai fi apărut înainte 
				boolean gasitTab1 = false;
				boolean Tab2ENou = true;
				String nmTab1 = joinTable.getValueAt(i, 0).toString();
				String nmTab2 = joinTable.getValueAt(i, 3).toString();
				int k = i;
				if (nmTab1.equals(nmTab2)) {
					Tab2ENou = false;
					break;
				}
				if (i == 0)
					gasitTab1 = true;
				while (k > 0) {
					k--;
					if (joinTable.getValueAt(k, 0).toString().equals(nmTab1) ||
						joinTable.getValueAt(k, 3).toString().equals(nmTab1)) {
						gasitTab1 = true;
					}
					if (joinTable.getValueAt(k, 0).toString().equals(nmTab2) ||
						joinTable.getValueAt(k, 3).toString().equals(nmTab2)) {
						Tab2ENou = false;
						break;	
					}
				}
				if (! gasitTab1 || ! Tab2ENou) {
					joinTable.clearSelection();
					joinTable.addRowSelectionInterval(i, i);
					JOptionPane.showMessageDialog(this, "Tabelul din stânga " +
					"(Tab 1) trebuie să mai apară în rândurile \nprecedente " +
						" iar tabelul din dreapta (Tab 2) trebuie să fie nou !",
						"Eroare", JOptionPane.ERROR_MESSAGE);
					eroareSintaxa = true;
					return;
						
				}
			}
			formareJoin();
			formareComanda();
		}
		
		public void formareJoin() {
			joinString = new StringBuffer("");
			joinHtmlString = new StringBuffer("");
			int nrTotRand = ((DefaultTableModel) joinTable.getModel(
				)).getRowCount();
			for (int i = 0; i < nrTotRand; i++) {
				String randStr = "";
				joinString.append(i == 0 ? " FROM " + joinTable.getValueAt(i, 0
					).toString() : "");
				joinString.append(" " + joinTable.getValueAt(i, 2).toString());
				joinString.append(" " + joinTable.getValueAt(i, 3).toString());
				joinString.append(" ON (" + joinTable.getValueAt(i, 1).toString(
					) + "=" + joinTable.getValueAt(i, 4).toString() + ")");

				joinHtmlString.append(i == 0 ? " FROM <font color=\"red\">" + 
					joinTable.getValueAt(i, 0).toString() + "</font>" : "");
				joinHtmlString.append(" "  + "<font color=\"blue\">" + 
					joinTable.getValueAt(i, 2).toString() + "</font>");
				joinHtmlString.append(" " + "<font color=\"red\">" + 
					joinTable.getValueAt(i, 3).toString() + "</font>");
				joinHtmlString.append(" <font color=\"blue\">ON </font>(" +
					"<font color=\"red\">" + 
					joinTable.getValueAt(i, 1).toString() + "</font>" + 
					"<font color=\"blue\"> = </font>" + "<font color=\"red\">" +
					joinTable.getValueAt(i, 4).toString() + "</font>)");
			}

			if (joinString.toString().equals(" FROM    ON (=)")) {
				joinString = new StringBuffer("");
				joinHtmlString = new StringBuffer("");
			}
			
		}
		
		public void itemStateChanged(ItemEvent e){
			int nrRand = joinTable.getEditingRow();
			JComboBox src = (JComboBox) e.getSource();
			if (nrRand == -1) return;
			int nrCol = joinTable.getEditingColumn();
			if (nrCol == -1) return;
			if (nrCol == 0 || nrCol == 3) {
				JComboBox comp = (JComboBox) ((DefaultCellEditor)
					joinTable.getCellEditor(nrRand, nrCol)).getComponent();
				String nmTab = (String) comp.getSelectedItem();	//tabel selectat
				if (src == tab1CBox)
					umpleListCp(nrRand, nmTab, true);
				else if (src == tab2CBox) {
					umpleListCp(nrRand, nmTab, false);
//dacă mai sunt cond. join, pe următorul rând în col. 0 punem ac. tabel	
					if (nrRand < ((DefaultTableModel) joinTable.getModel(
						)).getRowCount() -1) {
						joinTable.setValueAt(nmTab, nrRand + 1, 0);
						umpleListCp(nrRand + 1, nmTab, true);
					}
				}
			}
			else if (nrCol == 1) {
				String mesajStr = "";
				JComboBox comp = (JComboBox) ((DefaultCellEditor)
					joinTable.getCellEditor(nrRand, 1)).getComponent();
				String nmCpSel = (String) comp.getSelectedItem();	//cp. selectat
				String tipCpSel = wherePanel.cpHash.get(nmCpSel);
				if (nmCpSel == null ||tipCpSel == null) return;
				//cp. tabelului 2:
				String nmTab2 = (String)joinTable.getValueAt(nrRand, 3);
				if (nmTab2.equals(""))
					return;
				String cpCrt, tipCpCrt;
				for (int i = 0; i < cpTab2CBoxModel.getSize(); i++) {
					cpCrt = (String)cpTab2CBoxModel.getElementAt(i);
					tipCpCrt = wherePanel.cpHash.get(cpCrt);
					if (tipCpCrt != null && tipCpCrt.equals(tipCpSel))
						mesajStr += "<br>" + cpCrt; 
				}
				if (mesajStr.equals("")) {
					mesajStr += "<html>Tipul pt. " + nmCpSel + "<br>" + 
						tipCpSel + "<br>" + "În tabelul <br>" + nmTab2 + 
						"<br>nu există nici un câmp <br>de acest tip</html>" ;
				}
				else {
					mesajStr = "<html>Tipul pt. " + nmCpSel + "<br>" + 
						tipCpSel + "<br>" + "Din tabelul<br>" + nmTab2 +
						"<br>puteți alege<br>următoarele câmpuri:" 
						+ mesajStr + "</html>";
				}
				infoLabel.setText(mesajStr);
			}
			else if (nrCol == 4) {
				String mesajStr = "";
				JComboBox comp = (JComboBox) ((DefaultCellEditor)
					joinTable.getCellEditor(nrRand, 4)).getComponent();
				String nmCpSel = (String) comp.getSelectedItem();	//cp. selectat
				String tipCpSel = wherePanel.cpHash.get(nmCpSel);
				if (nmCpSel == null ||tipCpSel == null) return;
				//cp. tabelului 2:
				String nmTab1 = (String)joinTable.getValueAt(nrRand, 0);
				if (nmTab1.equals(""))
					return;
				String cpCrt, tipCpCrt;
				for (int i = 0; i < cpTab1CBoxModel.getSize(); i++) {
					cpCrt = (String)cpTab1CBoxModel.getElementAt(i);
					tipCpCrt = wherePanel.cpHash.get(cpCrt);
					if (tipCpCrt != null && tipCpCrt.equals(tipCpSel))
						mesajStr += "<br>" + cpCrt; 
				}
				if (mesajStr.equals("")) {
					mesajStr += "<html>Tipul pt. " + nmCpSel + "<br>" + 
						tipCpSel + "<br>" + "În tabelul <br>" + nmTab1 + 
						"<br>nu există nici un câmp <br>de acest tip</html>" ;
				}
				else {
					mesajStr = "<html>Tipul pt. " + nmCpSel + "<br>" + 
						tipCpSel + "<br>" + "Din tabelul<br>" + nmTab1 +
						"<br>puteți alege<br>următoarele câmpuri:" 
						+ mesajStr + "</html>";
				}
				infoLabel.setText(mesajStr);
			}
		}
		
		public void valueChanged(ListSelectionEvent e) {
			if (e.getValueIsAdjusting()) return;
			ListSelectionModel lsm = (ListSelectionModel)e.getSource();
			if (lsm.isSelectionEmpty()) 
				return;
			int selInd = lsm.getMinSelectionIndex();
			DefaultTableModel dtm = (DefaultTableModel)joinTable.getModel();
			String nmTab1 = (String)joinTable.getValueAt(selInd, 0);
			String nmTab2 = (String)joinTable.getValueAt(selInd, 3);
			umpleListCp(selInd, nmTab1, true);	//umple lista cu cp. tabelului 1
			umpleListCp(selInd, nmTab2, false);	//umple lista cu cp. tabelului 2
		}
	}
}
 
