package diploma;

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;

public class WherePanel extends JPanel implements ItemListener,  
	ActionListener, ListSelectionListener {
		StringBuffer whereString = new StringBuffer(),
		whereHtmlString = new StringBuffer();
		JTable criteriiTable;
		JFrame parinte;	//poate să apară în SELECT, DELETE, UPDATE
		InterfataGrafica interfataGrafica;
	String[] opLogArray = {"AND", "OR", ""}; 
	String[] opSelStrArray = {"=", "!=", ">", "<", ">=", "<=", 
		"BETWEEN AND", "IS NULL", "IS NOT NULL", "IN", "LIKE", ""};
	String[] opSelNoArray = {"=", "!=", ">", "<", ">=", "<=", 
		"BETWEEN AND", "IS NULL", "IS NOT NULL", ""};
	String[] opNotArray = {"", "NOT"};
	String[] paranDescArray = {"", "("}, paranIncArray = {"", ")"}, 
		nulArray = {""};
		boolean eWhere;		//poate fi where sau having
		boolean eroareSintaxa = false;	//la formarea comenzii where
//conține numele câmpului și tipul câmpului (pt. a ști operatorii) :
		Hashtable<String, String> cpHash;

		DefaultComboBoxModel parDescCBoxModel, parIncCBoxModel, 
		nulCBoxModel, opLogCBoxModel, numeCpCBoxModel, opSelNoCBoxModel, 
		opSelStrCBoxModel, opNotCBoxModel;
	private JComboBox opLogCBox, paran1CBox, paran2CBox, paran3CBox,
		opNotCBox, opSelCBox;
		JComboBox numeCpCBox;
		JButton validButton;
		JTextField exprAritmTxFld;
		JLabel exprAritmLabel;
		Hashtable<Integer, Integer> nivelImbricHash;	//asociem fiecărui rând
											//din tabel un nivel de imbricare
	private RedareColorCBox redareColorCel;
	
	//clasă ce afișează conținutul din celule :
	class RedareColorCBox extends JLabel implements TableCellRenderer {
		private Color culoare;
		private Color bejColor, rosuColor, verdeColor, galbenColor;
		public RedareColorCBox() {
			super();
			setOpaque(true);
			//Culorile în tabel pt. nivelurile de imbricare
			bejColor = new Color(245, 245, 220);
			rosuColor = new Color(255, 127, 127);
			galbenColor = new Color(255, 240, 0);
			verdeColor = new Color(0, 255, 127);
		}
		public Component getTableCellRendererComponent(JTable table, Object 
			value, boolean isSelected, boolean hasFocus, int row, int column) {
	        setText(value.toString());
	        Color culoare = bejColor;
	        int nivelImbricare = nivelImbricHash.get(new Integer(row));
	        switch (nivelImbricare) {
	        	case 1 :
	        		if (column > 0) 
	        			culoare = galbenColor;
	        		else culoare = bejColor;
	        		break;
	        	case 2 :
	        		if (column == 1)
	        			culoare = galbenColor;
	        		else if (column > 1)
	        			culoare = verdeColor;
	        		else culoare = bejColor;
	        		break;
	        	case 3 :
	        		if (column == 1)
	        			culoare = galbenColor;
	        		else if (column == 2)
	        			culoare = verdeColor;
	        		else if (column > 2)
	        			culoare = rosuColor;
	        		else culoare = bejColor;
	        		break;
	        }
	        setBackground(culoare);
	        return this;
		}
	}

	class AscultaLaCp implements ItemListener {
		private WherePanel parinte;
		public AscultaLaCp(WherePanel parinte) {
			this.parinte = parinte;
		}
		public void itemStateChanged(ItemEvent e) {
			int dim = numeCpCBox.getItemCount();	//câte item sunt în listă
			int selInd = numeCpCBox.getSelectedIndex();
			String nmCp = (String) numeCpCBox.getSelectedItem();
			//dacă e un nume de câmp din tabel :
			if (selInd < numeCpCBoxModel.getIndexOf("expresie aritmetică") - 1 
	 			&& selInd > -1 ) {
				String tipCp = cpHash.get(nmCp);
				if (tipCp.indexOf("int") > -1 || tipCp.indexOf("float") > -1 ||  
					tipCp.indexOf("double") > -1 || tipCp.indexOf("numeric") > -1 
					|| tipCp.indexOf("year") > -1) {	//tip număr
					opSelCBox.setModel(opSelNoCBoxModel);	
					}
				else opSelCBox.setModel(opSelStrCBoxModel);		//tip string
			}
			else if (nmCp.equals("")) {	//selectat cp nul
					exprAritmLabel.setEnabled(false);
					exprAritmTxFld.setEnabled(false);
					opSelCBox.setModel(nulCBoxModel);
			}
			else {			//expr. aritm.		
				opSelCBox.setModel(opSelNoCBoxModel);
				if (nmCp.equals("expresie aritmetică")) {	//expr aritm.  
					exprAritmLabel.setEnabled(true);
					exprAritmTxFld.setEnabled(true);
					int crtRow = criteriiTable.getEditingRow();	
					exprAritmTxFld.setInputVerifier(new 
						ExprAritmVerifier(parinte, crtRow, 5));
					exprAritmTxFld.requestFocusInWindow();
				}									
				else {
					exprAritmLabel.setEnabled(false);
					exprAritmTxFld.setEnabled(false);
				}
			}
		}
	}
	//poate fi where (eWhere = true) sau having (eWhere = false)
	public WherePanel(JFrame parinte, boolean eWhere) {
		super();
		this.parinte = parinte;
		this.eWhere = eWhere;
		this.interfataGrafica = interfataGrafica;
		setOpaque(true);
		redareColorCel = new RedareColorCBox();
		nivelImbricHash = new Hashtable<Integer, Integer>();
		cpHash = new Hashtable<String, String>();
		String[] colNumeArray = {"<html><center>Și/<br>Sau</center></html>", 
			"<html>Niv<br><center>1</center></html>",
			"<html>Niv<br><center>2</center></html>", 
			"<html>Niv<br><center>3</center></html>", 
			"Neg", "Nume câmp", "Criteriu", "Valoare"};
		//inițializăm tabelul cu șirul "" :
		String[][] date = new String[10][8];
		for (int i = 0; i < 10; i++) {
			nivelImbricHash.put(new Integer(i), new Integer(0));
			for (int j = 0; j < 8; j++)
				date[i][j] = "";
		}
		criteriiTable = new JTable(new DefaultTableModel(date, colNumeArray));
		criteriiTable.setPreferredScrollableViewportSize(new Dimension(
			500, 180));
		criteriiTable.setBackground(new Color(245, 245, 220));
		criteriiTable.setToolTipText("Pentru a edita o celulă, faceți dublu "
			+ "clic pe ea");
		//se va putea selecta un singur rând din tabel :
		criteriiTable.getSelectionModel().setSelectionMode(
			ListSelectionModel.SINGLE_SELECTION);
		//la fiecare selecție de rând trebuie calculat nivelul de imbricare pt.
		//a stabili corect item-urile din combobox-urile cu paranteze :
		criteriiTable.getSelectionModel().addListSelectionListener(this);
		criteriiTable.setDefaultRenderer(JComboBox.class, redareColorCel);
		criteriiTable.setDefaultRenderer(JTextField.class, redareColorCel);
		
		JScrollPane scrollPane = new JScrollPane(criteriiTable);
		//pt. coloana cu operatorii logici :
		TableColumn crtColumn = criteriiTable.getColumnModel().getColumn(0);
		opLogCBoxModel = new DefaultComboBoxModel(opLogArray);
		opLogCBox = new JComboBox(opLogCBoxModel);
		Font simpluFont = opLogCBox.getFont().deriveFont(Font.PLAIN, 11);
		opLogCBox.setFont(simpluFont);
		crtColumn.setCellEditor(new DefaultCellEditor(opLogCBox));
		crtColumn.setPreferredWidth(15);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
		//pt. cele 3 coloane cu nivelul de imbricare :
		nulCBoxModel = new DefaultComboBoxModel(nulArray);
		parDescCBoxModel = new DefaultComboBoxModel(paranDescArray);
		parIncCBoxModel = new DefaultComboBoxModel(paranIncArray);
		paran1CBox = new JComboBox(parDescCBoxModel);
		crtColumn = criteriiTable.getColumnModel().getColumn(1);
		paran1CBox.setFont(simpluFont);
		paran1CBox.addItemListener(this);
		crtColumn.setCellEditor(new DefaultCellEditor(paran1CBox));
		crtColumn.setPreferredWidth(15);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
		paran2CBox = new JComboBox(parDescCBoxModel);
		crtColumn = criteriiTable.getColumnModel().getColumn(2);
		paran2CBox.setFont(simpluFont);
		paran2CBox.addItemListener(this);
		crtColumn.setCellEditor(new DefaultCellEditor(paran2CBox));
		crtColumn.setPreferredWidth(15);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
		paran3CBox = new JComboBox(parDescCBoxModel);
		crtColumn = criteriiTable.getColumnModel().getColumn(3);
		paran3CBox.setFont(simpluFont);
		paran3CBox.addItemListener(this);
		crtColumn.setCellEditor(new DefaultCellEditor(paran3CBox));
		crtColumn.setPreferredWidth(15);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);

		//pt. coloana cu negația :
		crtColumn = criteriiTable.getColumnModel().getColumn(4);
		opNotCBoxModel = new DefaultComboBoxModel(opNotArray);
		opNotCBox = new JComboBox(opNotCBoxModel);
		opNotCBox.setFont(simpluFont);
		crtColumn.setCellEditor(new DefaultCellEditor(opNotCBox));
		crtColumn.setPreferredWidth(15);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
		//pt. coloana cu numele câmpului :
		crtColumn = criteriiTable.getColumnModel().getColumn(5);
		numeCpCBoxModel = new DefaultComboBoxModel();
		numeCpCBoxModel.addElement("");
		numeCpCBoxModel.addElement("expresie aritmetică");
		numeCpCBox = new JComboBox(numeCpCBoxModel);
		numeCpCBox.setFont(simpluFont);
		numeCpCBox.addItemListener(new AscultaLaCp(this));
		numeCpCBox.setEditable(true);
		crtColumn.setCellEditor(new DefaultCellEditor(numeCpCBox));
		crtColumn.setPreferredWidth(110);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
		//pt. coloana cu criteriul selecției :
		crtColumn = criteriiTable.getColumnModel().getColumn(6);
		opSelNoCBoxModel = new DefaultComboBoxModel(opSelNoArray);
		opSelStrCBoxModel = new DefaultComboBoxModel(opSelStrArray);
		opSelCBox = new JComboBox(new DefaultComboBoxModel(nulArray));
		opSelCBox.setFont(simpluFont);
		crtColumn.setCellEditor(new DefaultCellEditor(opSelCBox));
		crtColumn.setPreferredWidth(60);
		((DefaultCellEditor)crtColumn.getCellEditor()).setClickCountToStart(2);
		
		JPanel exprAritmPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		exprAritmPanel.setAlignmentX(0);
		exprAritmLabel = new JLabel("Expr. aritmetică : ", JLabel.LEFT);
		exprAritmTxFld = new JTextField();
		exprAritmTxFld.setPreferredSize(new Dimension(240, 20));
		exprAritmTxFld.setFont(simpluFont);
		exprAritmTxFld.setEnabled(false);
		if (! eWhere)
			exprAritmTxFld.setToolTipText("Expresia trebuie să conțină cel " +
				"puțin un câmp din \'Nume câmp\'");
		exprAritmLabel.setLabelFor(exprAritmTxFld);
		exprAritmLabel.setDisplayedMnemonic(KeyEvent.VK_X);
		exprAritmLabel.setEnabled(false);
		exprAritmPanel.add(exprAritmLabel);
		exprAritmPanel.add(exprAritmTxFld);
		
		validButton = new JButton("Validează");
		validButton.addActionListener(this);
		validButton.setMnemonic(KeyEvent.VK_V);
		validButton.setSize(40, 20);
		JPanel butPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 80));
		butPanel.add(validButton);
		
		this.setLayout(new BorderLayout());
		add(scrollPane, BorderLayout.CENTER);
		add(exprAritmPanel, BorderLayout.SOUTH);
		add(butPanel, BorderLayout.EAST);
		
	}			
	
	public void itemStateChanged(ItemEvent e) {
		int selRow = criteriiTable.getEditingRow();
		JComboBox sursa = (JComboBox)e.getSource();
		if (sursa.getSelectedItem().toString().equals("(") ||
			sursa.getSelectedItem().toString().equals(")")) {
			String nmCp = (String)criteriiTable.getValueAt(selRow, 5);
			String critSel = (String)criteriiTable.getValueAt(selRow, 6);
			String valComp = (String)criteriiTable.getValueAt(selRow, 7);
			if (! nmCp.equals("")) {
//dacă avem cp și criterii pe rândul cu paranteză, coborâm info un rând mai jos				
				String[] rand = {"", "", "", "", "", "", "", ""};
				((DefaultTableModel)criteriiTable.getModel()).insertRow(
					selRow + 1, rand);
				criteriiTable.setValueAt("", selRow, 5);
				criteriiTable.setValueAt("", selRow, 6);
				criteriiTable.setValueAt("", selRow, 7);
				criteriiTable.setValueAt(nmCp, selRow + 1, 5);
				criteriiTable.setValueAt(critSel, selRow + 1, 6);
				criteriiTable.setValueAt(valComp, selRow + 1, 7);
			}
	//dezactivăm componentele din dreapta parantezei :
			int selCol = criteriiTable.getEditingColumn();
			for (int i = selCol + 1; i < 7; i++) {
				Component comp = ((DefaultCellEditor)
					criteriiTable.getCellEditor(selRow, i)).getComponent();
				JComboBox cb = (JComboBox)comp;
				cb.setModel(nulCBoxModel);				
			}
		//pe rândul cu paranteza închisă nu trebuie să fie AND sau OR :
			if (sursa.getSelectedItem().toString().equals(")")) {
				int rand = criteriiTable.getEditingRow();
				Component comp = ((DefaultCellEditor)
					criteriiTable.getCellEditor(rand, 0)).getComponent();
				JComboBox cb = (JComboBox)comp;
				cb.setModel(nulCBoxModel);
				criteriiTable.setValueAt("", rand, 0);
			}
	//pe un rând mai jos de paranteza deschisă nu trebuie să fie AND sau OR :
			else {
				int rand = criteriiTable.getEditingRow();
				Component comp = ((DefaultCellEditor)
					criteriiTable.getCellEditor(rand + 1, 0)).getComponent();
				JComboBox cb = (JComboBox)comp;
				cb.setModel(nulCBoxModel);
				criteriiTable.setValueAt("", rand + 1, 0);
			}
		}
//colorăm întreg tabelul :
		if (sursa.equals(paran1CBox) || sursa.equals(paran2CBox) ||
			sursa.equals(paran3CBox)) {
			int noRandTable = 				//nr de rânduri din tabel
				((DefaultTableModel)criteriiTable.getModel()).getRowCount();
			int nivelImbricare = 0;	//
			for (int crtRand = 0; crtRand < noRandTable; crtRand++) {
				if (criteriiTable.getValueAt(crtRand, 1).equals("(")) {
					nivelImbricare = 1;
					nivelImbricHash.put(new Integer(crtRand), new Integer(1));
				}
				else if (criteriiTable.getValueAt(crtRand, 1).equals(")")) {
					nivelImbricHash.put(new Integer(crtRand), new Integer(1));
					nivelImbricare = 0;
				}
				else if (criteriiTable.getValueAt(crtRand, 2).equals("(")) {
					nivelImbricare = 2;
					nivelImbricHash.put(new Integer(crtRand), new Integer(2));
				}
				else if (criteriiTable.getValueAt(crtRand, 2).equals(")")) {
					nivelImbricHash.put(new Integer(crtRand), new Integer(2));
					nivelImbricare = 1;
				}
				else if (criteriiTable.getValueAt(crtRand, 3).equals("(")) {
					nivelImbricare = 3;
					nivelImbricHash.put(new Integer(crtRand), new Integer(3));
				}
				else if (criteriiTable.getValueAt(crtRand, 3).equals(")")) {
					nivelImbricHash.put(new Integer(crtRand), new Integer(3));
					nivelImbricare = 2;
				}
				else {
					nivelImbricHash.put(new Integer(crtRand), new Integer(
						nivelImbricare));
				}
			}
			criteriiTable.revalidate();
      		criteriiTable.repaint();
		}
	}
	
	public boolean randGol(int i) {
		int dim = ((DefaultTableModel)criteriiTable.getModel()).getRowCount();
		if (i < 0 || i >= dim) throw new IndexOutOfBoundsException();
		else {
			for (int j = 0; j < 8; j++)
				if (! criteriiTable.getValueAt(i, j).equals(""))
					return false;
			return true;
		}
	}
	
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("Validează")) {
			eroareSintaxa = false;
			int dim = ((DefaultTableModel)criteriiTable.getModel(
				)).getRowCount();
			int nrPar1 = 0, nrPar2 = 0, nrPar3 = 0;
			for (int i = 0; i < dim; i++) {
				if (! criteriiTable.getValueAt(i, 0).toString().equals("")
					&& criteriiTable.getValueAt(i, 1).toString().equals("")
					&& criteriiTable.getValueAt(i, 2).toString().equals("")
					&& criteriiTable.getValueAt(i, 3).toString().equals("")
					&& criteriiTable.getValueAt(i, 5).toString().equals("")) {
					JOptionPane.showMessageDialog(this, "Pe rândul " + 
					new Integer(i + 1) + " coloana cu numele câmpului "
					+ "nu trebuie să fie nulă !", "Eroare !",
						JOptionPane.ERROR_MESSAGE);
					criteriiTable.clearSelection();
					criteriiTable.addRowSelectionInterval(i, i);
					eroareSintaxa = true;
					return;
				}
				if (i > 0 && criteriiTable.getValueAt(i, 0).toString().equals(
					"")) {
					int j;	//pt. coloane
					int k = i - 1; 	//verifică rândurile superioare
					while (k  > 0 && randGol(k)) 
						k--;
					boolean primaCond = true, aDouaCond = false;
					if (k == 0 && randGol(k))
						primaCond = false;
					for (j = 1; j < 4; j++) {
						if (criteriiTable.getValueAt(k, j).toString(
							).equals("(")) {
							primaCond = false;
							break;	
						}
					}	//a 2-a cond : rândul curent să nu fie gol
					for (j = 1; j < 4; j++) {
						if (criteriiTable.getValueAt(i, j).toString(
							).equals("(")) {
							aDouaCond = true;
							break;	
						}
					}
					if (! criteriiTable.getValueAt(i, 5).toString().equals(""))
						aDouaCond = true; 
					if (primaCond && aDouaCond) {
						JOptionPane.showMessageDialog(this, "Pe rândul " + 
							new Integer(i + 1) + " coloana Și/Sau "
							+ "nu trebuie să fie nulă !","Eroare !",
							JOptionPane.ERROR_MESSAGE);
						criteriiTable.clearSelection();
						criteriiTable.addRowSelectionInterval(i, i);
						eroareSintaxa = true;
						return;
					}
				}
				if (! criteriiTable.getValueAt(i, 5).toString().equals("")
					&& criteriiTable.getValueAt(i, 6).toString().equals("")) {
					JOptionPane.showMessageDialog(this, "Pe rândul " + 
					new Integer(i + 1) + " coloana având criteriul de selecție "
					+ "nu trebuie să fie nulă !", "Eroare !",
						JOptionPane.ERROR_MESSAGE);
					criteriiTable.clearSelection();
					eroareSintaxa = true;
					criteriiTable.addRowSelectionInterval(i, i);
					return;
				}
				if (criteriiTable.getValueAt(i, 5).toString().equals("")
					&& ! criteriiTable.getValueAt(i, 4).toString().equals("")) {
					JOptionPane.showMessageDialog(this, "Pe rândul " + 
					new Integer(i + 1) + " coloana cu negația "
					+ "trebuie să fie nulă !", "Eroare !",
						JOptionPane.ERROR_MESSAGE);
					criteriiTable.clearSelection();
					criteriiTable.addRowSelectionInterval(i, i);
					eroareSintaxa = true;
					return;
				}
				if (criteriiTable.getValueAt(i, 6).toString().equals("") ||
					criteriiTable.getValueAt(i, 6).toString().equals("IS NULL")
					|| criteriiTable.getValueAt(i, 6).toString().equals(
						"IS NOT NULL")) {
					if (! criteriiTable.getValueAt(i, 7).toString().equals("")) {
						JOptionPane.showMessageDialog(this, "Pe rândul " + 
						new Integer(i + 1) + 
						" coloana cu valoarea trebuie să fie nulă !", "Eroare !",
							JOptionPane.ERROR_MESSAGE);
						criteriiTable.clearSelection();
						criteriiTable.addRowSelectionInterval(i, i);
						eroareSintaxa = true;
						return;
					}
				}
				else {
					if (criteriiTable.getValueAt(i, 7).toString().equals("")) {
						JOptionPane.showMessageDialog(this, "Pe rândul " + 
						new Integer(i + 1) + 
						" coloana cu valoarea nu trebuie să fie nulă !", 
						"Eroare !", JOptionPane.ERROR_MESSAGE);
						criteriiTable.clearSelection();
						criteriiTable.addRowSelectionInterval(i, i);
						eroareSintaxa = true;
						return;
					}
					else if (criteriiTable.getValueAt(i, 6).toString().equals(
						"BETWEEN AND") && criteriiTable.getValueAt(
						i, 7).toString().split(",").length != 2) {
						JOptionPane.showMessageDialog(this, "Pe rândul " + 
						new Integer(i + 1) + 
						" coloana cu valoarea trebuie să aibă \ndouă valori" 
						+ " despărțite prin virgulă !", 
						"Eroare !", JOptionPane.ERROR_MESSAGE);
						criteriiTable.clearSelection();
						criteriiTable.addRowSelectionInterval(i, i);
						eroareSintaxa = true;
						return;
					}
				}
				if (criteriiTable.getValueAt(i, 1).equals("("))
					nrPar1++;
				else if (criteriiTable.getValueAt(i, 1).equals(")"))
					nrPar1--;
				else if (criteriiTable.getValueAt(i, 2).equals("("))
					nrPar2++;
				else if (criteriiTable.getValueAt(i, 2).equals(")"))
					nrPar2--;
				else if (criteriiTable.getValueAt(i, 3).equals("("))
					nrPar3++;
				else if (criteriiTable.getValueAt(i, 3).equals(")"))
					nrPar3--;
			}
			String mesajStr = "";
			mesajStr += nrPar1 != 0 ? "Pe nivelul de imbricare unu, nr. " + 
			"parantezelor deschise este mai " + (nrPar1 > 0 ? "mare " : "mic ") 
			+ "decât al celor închise !\n" : "";
			mesajStr += nrPar2 != 0 ? "Pe nivelul de imbricare doi, nr. " + 
			"parantezelor deschise este mai " + (nrPar2 > 0 ? "mare " : "mic ") 
			+ "decât al celor închise !\n" : "";
			mesajStr += nrPar3 != 0 ? "Pe nivelul de imbricare trei, nr. " + 
			"parantezelor deschise este mai " + (nrPar3 > 0 ? "mare " : "mic ") 
			+ "decât al celor închise !\n" : "";
			if (! mesajStr.equals("")) {
				JOptionPane.showMessageDialog(this, mesajStr, "Eroare !",
					JOptionPane.ERROR_MESSAGE);
				eroareSintaxa = true;
				return;
			}
					//tabelul e corect, formăm comenzile :
			compuneClauzaWhere();
			if (parinte instanceof Interogare)
				((Interogare)parinte).formareComanda();
			else if (parinte instanceof StergeInregistrari)
				((StergeInregistrari)parinte).formareComanda();
			else if (parinte instanceof ActualizareInregistrari)
				((ActualizareInregistrari)parinte).formareComanda();
			
		}
	}
	
	public void compuneClauzaWhere() {
		if (eWhere) {
			whereString = new StringBuffer(" WHERE ");
			whereHtmlString = new StringBuffer(" WHERE ");
		}
		else {
			whereString = new StringBuffer(" HAVING ");
			whereHtmlString = new StringBuffer(" HAVING ");
		}
		int dim = ((DefaultTableModel)criteriiTable.getModel(
			)).getRowCount();
		for (int i = 0; i < dim; i++) {
			if (randGol(i)) continue;
			for (int j = 0; j < 8; j++) {
				String valStr = criteriiTable.getValueAt(i, j).toString();
				if ( ! valStr.equals("")) {
					switch (j) {
						case 0 : case 1 : case 2 : case 3 :
						whereString = whereString.append(" " + valStr);	
						whereHtmlString = whereHtmlString.append(" " + valStr);
						break;
						case 4 :	
						whereString = whereString.append(" " + valStr);	
						whereHtmlString = whereHtmlString.append(
							" <font color=\"blue\">" + valStr + "</font>");
						break;
						case 5 :
						whereString = whereString.append(" " + valStr);	
						int indLit = 0;		//parcuge expr. aritm.
						int primLit = 0;	//indicele primei litere a cp.
						int len = valStr.length();
						while (indLit < len) {
							if (! Character.isLetter(valStr.charAt(indLit))) {
								while (indLit < len && ! Character.isLetter(
									valStr.charAt(indLit)))
									indLit++;
								if (indLit == len)
									break;
							}
							primLit = indLit;
							char crtChar = valStr.charAt(indLit);
							while (indLit < len && (crtChar = valStr.charAt(
								indLit)) != ' ' && crtChar != '\t' && 
								crtChar != '(' && crtChar != ')' && 
								crtChar != '+' && crtChar != '-' && crtChar != 
								'*' && crtChar != '/') {
								indLit++;	
							} 
							String cpDinExpr = 	valStr.substring(primLit, 
								indLit);
							cpDinExpr = "<font color=\"red\">" + cpDinExpr +
								"</font>";
							int lg = "<font color=\"red\"></font>".length();
							valStr = (primLit > 0 ? valStr.substring(0, primLit)
								: "") + cpDinExpr + (indLit < len ? 
								valStr.substring(indLit, len) : "");
							indLit += lg;
							len += lg;
						}
						whereHtmlString = whereHtmlString.append(
							" " + valStr);
						break;
						case 6 :
						whereString = whereString.append(" " + valStr);	
						if (valStr.equals("<"))
							valStr = "&lt;";		//pt html
						else if (valStr.equals("<="))
							valStr = "&lt;=";
						if (valStr.equals("BETWEEN AND"))
							valStr = "<font color=\"blue\">BETWEEN</font> " +
								"<font color=\"blue\">AND</font>";
						else valStr = "<font color=\"blue\">" + valStr +
							"</font>";
						whereHtmlString = whereHtmlString.append(
							" " + valStr);
							break;
						case 7 :
						String nmCp = (String) criteriiTable.getValueAt(i, 5);
						String valComp = (String)criteriiTable.getValueAt(i, 7);
						String opComp = (String)criteriiTable.getValueAt(i, 6);
						if (valComp.equals(""))
							break;
						String tipCp = "";
						int selInd = numeCpCBoxModel.getIndexOf(nmCp);
						//dacă e un nume de câmp din tabel :
						if (! opComp.equals("BETWEEN AND") &&
							! opComp.equals("IN")) {
							if (selInd < numeCpCBoxModel.getIndexOf(
								"expresie aritmetică") - 1 && selInd > -1 ) {
								tipCp = cpHash.get(nmCp);
								if (tipCp.indexOf("int") < 0 && tipCp.indexOf(
									"float") < 0 && tipCp.indexOf("double") < 0 
									&& tipCp.indexOf("numeric") < 0 &&
									tipCp.indexOf("year") < 0) {	//nu e tip număr
									valComp = "\'" + valComp + "\'";
								}
							}
							whereString = whereString.append(" " + valComp);
							whereHtmlString = whereHtmlString.append(" " + 
								"<font color=\"green\">" + valComp + "</font>");
						}
						else {		//avem BETWEEN AND sau IN
							String[] multString = valComp.split(",");
							String inString = "";
							for (String artCrtString : multString) {
								artCrtString = artCrtString.trim();
								artCrtString = new String("\'" + artCrtString +
									"\'");
								inString = inString.equals("") ? 
									artCrtString :
									inString + ", " + artCrtString;
							}
							if (opComp.equals("IN")) {
								whereString = whereString.append(" (" + inString
									+ ")");
								whereHtmlString = whereHtmlString.append(
									" (<font color=\"green\">" + inString +
									"</font>)");
							}
							else {		//avem BETWEEN AND
								multString[0] = multString[0].trim();
								multString[1] = multString[1].trim();
								if (eWhere)
									tipCp = cpHash.get(nmCp);
								if (tipCp.indexOf("int") < 0 && tipCp.indexOf(
									"float") < 0 && tipCp.indexOf("double") < 0 
									&& tipCp.indexOf("numeric") < 0 && 
									 tipCp.indexOf("year") < 0 && eWhere) {	//nu e tip număr
									multString[0] = new String("\'" + 
										multString[0] + "\'");
									multString[1] = new String("\'" + 
										multString[1] + "\'");
								}
								whereString = new StringBuffer(
									whereString.substring(0, whereString.length(
									) - 3)).append(multString[0]).append(
									" AND ").append(multString[1]);
								whereHtmlString = whereHtmlString.insert(
									whereHtmlString.lastIndexOf(
									"<font color=\"blue\">AND"), 
									"<font color=\"green\">" + multString[0] +
									"</font> ");
								whereHtmlString = whereHtmlString.append(
									" <font color=\"green\">" + multString[1] +
									"</font>");
							}
						}
					}
				}
			}
		}
		if (whereString.toString().equals(" WHERE ") || 
			whereString.toString().equals(" HAVING ")) {
			whereString = new StringBuffer("");	
			whereHtmlString = new StringBuffer("");	
		}
	}
	
	//la selectarea unui alt rând din tabel :
	public void valueChanged(ListSelectionEvent e) {
		if (e.getValueIsAdjusting()) return;
		numeCpCBox.setModel(numeCpCBoxModel);
		ListSelectionModel lsm = (ListSelectionModel)e.getSource();
		if (lsm.isSelectionEmpty()) return;
		int selInd = lsm.getMinSelectionIndex();
		DefaultTableModel dtm = (DefaultTableModel)criteriiTable.getModel();
		int noRandTable = dtm.getRowCount();		//nr de rânduri din tabel
		if (selInd == noRandTable - 1) {
			int dim = nivelImbricHash.size();
			nivelImbricHash.put(new Integer(dim), new Integer(0));
			String[] rand = {"", "", "", "", "", "", "", ""};
			dtm.addRow(rand);
		}
//oricând selectăm un rând, dacă are paranteze combobox-urile trebuie
//să fie goale :
		if (! criteriiTable.getValueAt(selInd, 1).toString().equals("")) {
			paran2CBox.setModel(nulCBoxModel);
			paran3CBox.setModel(nulCBoxModel);
			numeCpCBox.setModel(nulCBoxModel);
		}
		else if (! criteriiTable.getValueAt(selInd, 2).toString().equals("")) {
			paran1CBox.setModel(nulCBoxModel);
			paran3CBox.setModel(nulCBoxModel);
			numeCpCBox.setModel(nulCBoxModel);
		}
		else if (! criteriiTable.getValueAt(selInd, 3).toString().equals("")) {
			paran1CBox.setModel(nulCBoxModel);
			paran2CBox.setModel(nulCBoxModel);
			numeCpCBox.setModel(nulCBoxModel);
		}	
		int crtInd = selInd;	
		int nivelImbricare = 0;
		if (selInd == 0) {
			opLogCBox.setModel(nulCBoxModel);	//primul rând nu are OR sau AND 
			nivelImbricare = 0;			
		}
		else {
			boolean toateRandurileDeMaiSusSuntGoale = true;
			while (--crtInd > -1 && criteriiTable.getValueAt(crtInd, 1).equals(
				"") && criteriiTable.getValueAt(crtInd, 2).equals("")
				&& criteriiTable.getValueAt(crtInd, 3).equals(""))
				if (! randGol(crtInd)) 
					toateRandurileDeMaiSusSuntGoale = false;
	//primul termen dintr-o paranteză ( nu are AND sau OR, ci paranteza are :
			if (crtInd == -1 && toateRandurileDeMaiSusSuntGoale)
				opLogCBox.setModel(nulCBoxModel);
			else if (crtInd == -1 && ! toateRandurileDeMaiSusSuntGoale)
				opLogCBox.setModel(opLogCBoxModel);
	//pe rândul cu paranteză închisă nu poate fi AND sau OR :
			else if (criteriiTable.getValueAt(selInd, 1).equals(")")
				|| criteriiTable.getValueAt(selInd, 2).equals(")")
				|| criteriiTable.getValueAt(selInd, 3).equals(")")) {
				opLogCBox.setModel(nulCBoxModel);	
			}
			else if (criteriiTable.getValueAt(crtInd, 1).equals("(")
				|| criteriiTable.getValueAt(crtInd, 2).equals("(")
				|| criteriiTable.getValueAt(crtInd, 3).equals("(")) {
				int k = crtInd + 1;
				while (k < selInd && randGol(k)) 
					k++;
				if (k == selInd)
					opLogCBox.setModel(nulCBoxModel);
				else opLogCBox.setModel(opLogCBoxModel);
			}
			else opLogCBox.setModel(opLogCBoxModel);
			if (crtInd == -1)	//rândurile de deasupra n-au avut 
				nivelImbricare = 0;		//nici un fel de paranteze
			else {	//apare paranteză pe un rând de mai sus 
				if (criteriiTable.getValueAt(crtInd, 1).equals("("))
					nivelImbricare = 1;
				else if (criteriiTable.getValueAt(crtInd, 1).equals(
					")"))
					nivelImbricare = 0;
				else if (criteriiTable.getValueAt(crtInd, 2).equals(
					"("))
					nivelImbricare = 2;
				else if (criteriiTable.getValueAt(crtInd, 2).equals(
					")"))
					nivelImbricare = 1;
				else if (criteriiTable.getValueAt(crtInd, 3).equals(
					"("))
					nivelImbricare = 3;
				else if (criteriiTable.getValueAt(crtInd, 3).equals(
					")"))
					nivelImbricare = 2;
			}
		}
		switch (nivelImbricare) {
			case 0 :
				paran1CBox.setModel(parDescCBoxModel);
				paran2CBox.setModel(nulCBoxModel);
				paran3CBox.setModel(nulCBoxModel);
				break;
			case 1 :
				paran1CBox.setModel(parIncCBoxModel);
				paran2CBox.setModel(parDescCBoxModel);
				paran3CBox.setModel(nulCBoxModel);
				
				break;
			case 2 :
				paran1CBox.setModel(nulCBoxModel);
				paran2CBox.setModel(parIncCBoxModel);
				paran3CBox.setModel(parDescCBoxModel);
				
				break;
			case 3 :
				paran1CBox.setModel(nulCBoxModel);
				paran2CBox.setModel(nulCBoxModel);
				paran3CBox.setModel(parIncCBoxModel);
				
				break;
		}
		if (criteriiTable.getValueAt(selInd, 1).equals("")
			&& criteriiTable.getValueAt(selInd, 2).equals("")
			&& criteriiTable.getValueAt(selInd, 3).equals("")) {
			opNotCBox.setModel(opNotCBoxModel);
			numeCpCBox.setModel(numeCpCBoxModel);
		}
	}	

/*	public static void createUIFrame() {
			JFrame prob = new JFrame();
			prob.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			prob.setDefaultLookAndFeelDecorated(true);
			WherePanel wherePanel = new WherePanel();
			prob.setContentPane(wherePanel);
			prob.pack();
			prob.setVisible(true);
	}
	public static void main(String args[])
	{
		SwingUtilities.invokeLater(new Runnable() {
			public void run(){
				createUIFrame();
			}
		});
	}*/
}	
