
Deprecated: Function set_magic_quotes_runtime() is deprecated in /DISK2/WWW/lokiware.info/mff/wakka.php on line 35
package zapoctovadb;

/*
 * Pro ucely snadneho publikovani na webu splacnuto do jednoho souboru,
 * jinak by to byly tri soubory (tri tridy).
 */

/*
 * Je mozne, ze reseni neni spravne, protoze jsem ho nestacil ve skole dokoncit
 * (viz komentare "Nasledujici radky jsem ve skole nestihl").
 * Nicmene doma jsem ho dopsal tak, ze by melo byt v funkcni presne podle zadani.
 * Omlouvam se za neprehlednost, nektere casti jsem psal dost ve spechu.
 */

import java.io.*;
import java.util.*;

public class ZapoctovaDB {	
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        BufferedReader  in  = new BufferedReader( new InputStreamReader(System.in));
        Database        db  = new Database(new File("."), System.err);
        String          cmd = null;
        try{
           while( db.processCmd( in.readLine() ) )
               ;
        }catch(IOException ex){
            System.err.println("Error reading input.");
            System.exit(1);
        }
    }

}




/*public */  class Database {
	
	private PrintStream         err;
	private File                dir;
	private Map<String,Table>   tables = new HashMap<String,Table>();
	
	public Database(File dbDir, PrintStream errStream){
		dir = dbDir;
		err = errStream;
		
		File[] dbFiles = dir.listFiles(new FilenameFilter(){
									   public boolean accept(File dir, String name){
									   return name.endsWith(".db");
									   }
									   });
		
		
		for(File f: dbFiles){
			try{
				tables.put( f.getName(), Table.existingTable(f) );
			}catch(IOException ex){
				/* ignore */
			}
		}
		
		err.printf("Path: %s\n", dir.getAbsolutePath());
		err.printf("Tables: %s\n", tables); /*TODO */
		
	}
	
	private static String tableName(String table){
		return table.concat(".db");
	}
	private File tableFile(String tableName){
		return new File(dir,tableName);
	}
	
	private static String checkList(String args){
		if(args.length()==0)
			return "Error: Missing list.";
		if(args.charAt(0) != '(')
			return "Error: List doesn't start with a '('.";
		if( args.charAt(args.length()-1) != ')' )
			return "Error: List doesn't end with a ')'.";
		return null;
	}
	private static String checkVList(String args){
		String err = checkList(args);
		if(err !=null)
			return err;
		args = args.substring(1, args.length()-1);
		if(args.length()==0)
			return "Error: Missing list value.";
		if(args.charAt(0) != '"')
			return "Error: Value list doesn't start with a '\"'.";
		if( args.charAt(args.length()-1) != '"' )
			return "Error: Value list doesn't end with a '\"'.";
		return null;
	}
	private static String[] unList(String args){
		String[] r = args.substring(1, args.length()-1).split(",\\s*",-1);
		if(r.length == 0 || r[0].length() == 0)
			return null;
		return r;
	}
	private static String[] unVList(String args){
		String[] r = args.substring(2, args.length()-2).split("\"\\s*,\\s*\"",-1);
		if(r.length == 0)
			return null;
		return r;
	}
	
	private String processCreate(String table, String args){
		String  tn  = tableName(table);
		File    tf  = this.tableFile(tn);
		String  e   = checkList(args);
		if(e != null)
			return e;
		
		String cols[] = unList(args);
		if(cols == null)
			return "Error: Empty column list.";
		Table   t   = null;
		
		/* * * * Nasledujici radky jsem ve skole nestihl:  * * * */
		if(new HashSet( Arrays.asList(cols) ).size() != cols.length)
			return "Duplicate column names.";
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
		
		try{
			t = Table.newTable(tf, cols);
		}catch(IOException ex){
			return "Internal Error: Creating table.";
		}
		
		if(t == null)
			return "Error: Table of that name already exists.";
		
		tables.put(tn, t);
		
		return "OK created.";
	}
	
	
	private String processInsert(String table, String args){
		Table t = tables.get( tableName(table) );
		if(t == null)
			return "Error: table doesn't exist.";
		
		String  e   = checkVList(args);
		if(e != null)
			return e;
		
		String values[] = unVList(args);
		if(values == null)
			return "Error: Empty value list.";
		
		return t.insert(values);
	}
	
	
	private String processDelete(String table, String args){
		Table t = tables.get( tableName(table) );
		if(t == null)
			return "Error: table doesn't exist.";
		String w[] = args.split("=\"",2);
		if(w.length !=2 || w[1].charAt(w[1].length()-1)!='\"')
			return "Error: Bad WHERE.";
		return t.delete(w[0],w[1].substring(0,w[1].length()-1));
	}
	
	
	private String processDrop(String table){
		Table t = tables.get( tableName(table) );
		if(t == null)
			return "Error: table doesn't exist.";
		t.drop();
		return "OK dropped.";
	}
	
	
	public static boolean cmdEq(String s, String t){
		if(s==t)
			return true;
		if(s == null || t == null)
			return false;
		return s.compareToIgnoreCase(t) == 0;
	}
	
	private boolean cmdCheck(String cmd0,String cmd1,String expected){
		if(cmdEq(cmd1,expected))
			return true;
		err.printf("Error: Command \"%s\" should be followed by \"%s\".\n", cmd0, expected);
		return false;
	}
	
	public boolean processCmd(String cmd) {
		if( cmd == null || cmdEq(cmd,"EXIT") )
			return false;
		String[] words = cmd.split("\\s+", 4);
		if (words.length < 3){
			err.println("Error: Command too short.");
			return true;
		}
		String cmd0     = words[0];
		String cmd1     = words[1];
		String table    = words[2];
		String args     = (words.length==4) ? words[3] : null;
		String result   = null;
		
		if(cmdEq(cmd0,"CREATE")){
			if( ! cmdCheck(cmd0, cmd1, "TABLE") )
				return true;
			if( args == null)
				result = "Error: Missing column list.";
			else
				result = this.processCreate(table,args);
		}else if(cmdEq(cmd0,"INSERT")){
			if( ! cmdCheck(cmd0, cmd1, "INTO") )
				return true;
			if( args == null)
				result = "Error: Missing VALUES.";
			else{
				words = args.split("\\s+", 2);
				if(words.length!=2)
					result = "Error missing value list.";
				else if( ! cmdCheck(cmd0, words[0], "VALUES") )
					return true;
				else
					result = this.processInsert(table,words[1]);
				
			}
		}else if( cmdEq(cmd0,"DELETE") ){
			if( ! cmdCheck(cmd0, cmd1, "FROM") )
				return true;
			if( args == null)
				result = "Error: Missing WHERE.";
			else{
				words = args.split("\\s+", 2);
				if(words.length!=2)
					result = "Error missing where clause.";
				else if( ! cmdCheck(cmd0, words[0], "WHERE") )
					return true;
				else
					result = this.processDelete(table,words[1]);
			}
		}else if(cmdEq(cmd0,"DROP")){
			if( ! cmdCheck(cmd0, cmd1, "TABLE") )
				return true;
			if( args != null )
				result = "Error: Stray arguments for DROP TABLE.";
			else
				result = this.processDrop(table);
		}else
			result = "Error: Unrecognized command.";
		
		if(result != null)
			err.println(result);
		else
			err.println("Internal Error: no result.");
		
		return true;
	}
	
}



/*public*/  class Table{
	private File        file;
	private String[]    cols;
	
	public String toString(){
		return "table( ".concat( concat("; ",cols) ).concat(" )");
	}
	
	public static String concat(String s, String[] as){
		String r = "";
		if(as.length == 0)
			return r;
		if(as.length > 1){
			for(String a : Arrays.copyOf(as, as.length-1))
				r = r.concat(a).concat(s);
		}
		return r.concat(as[as.length-1]);
	}
	
	private Table(File f, String[] c){
		file = f;
		cols = c;
	}
	
	public static Table newTable(File f, String[] c) throws IOException{
		if(f.exists())
			return null;
		
		PrintWriter fw = new PrintWriter( new FileWriter(f));
		fw.println( concat(";",c) );
		fw.close();
		
		return new Table(f, c);
	}
	
	public ArrayList<String[]> read() throws IOException{
		ArrayList<String[]>       r = new ArrayList<String[]>();
		BufferedReader  fr     = new BufferedReader( new FileReader(file));
		
		String row = fr.readLine();
		
		while( (row = fr.readLine()) != null)
			r.add(row.split(";",-1));
		fr.close();
		return r;
	}
	
	public void write(ArrayList<String[]> r) throws IOException{
		
		PrintWriter fw = new PrintWriter( new FileWriter(file));
		fw.println( concat(";",cols) );
		
		for(String[] row : r)
			fw.println( concat(";",row) );
		
		fw.close();
		
	}
	
	
	public static Table existingTable(File f) throws IOException{
		if( ! f.exists())
			return null;
		
		BufferedReader  fr     = new BufferedReader( new FileReader(f));
		String          head   = fr.readLine();
		fr.close();
		
		/* TODO TODO if(head == null) */
		assert head != null;
		String[] c = head.split(";",-1);
		
		return new Table(f, c);
	}
	
	public void drop(){
		file.delete();
		file = null;
	}
	
	public String insert(String[] values){
		if(values.length != cols.length)
			return "Error: Doesn't match column number.";
		
		try{
			ArrayList<String[]> r = read();
			r.add(values);
			write(r);
		}catch(IOException ex){
			return "Inernal error.";
		}
		
		return "OK inserted";
	}
	
	
	public String delete(String col, String value){
		int index = Arrays.asList(cols).indexOf(col);
		if(index < 0)
			return "Error: Bad column.";
		
		try{
			ArrayList<String[]> r = read();
			/* * * * Nasledujici radky jsem ve skole nestihl:  * * * */
			ArrayList<String[]> d = new ArrayList<String[]>();
			for(String[] row : r){
				if(row[index].equals(value))
					d.add(row);
			}
			r.removeAll(d);
			/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
			write(r);
		}catch(IOException ex){
			return "Inernal error.";
		}
		
		return "OK deleted";
	}
	
}