diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/Main.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/Main.java new file mode 100644 index 000000000..baecbdc57 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/Main.java @@ -0,0 +1,48 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Interpreter; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; +import java.util.HashSet; +import java.util.Set; + +public class Main { // Using JSON format. + public static void main(final String[] args) throws Exception { + new MakeDirs().execute(null); + Set commandSet = new HashSet<>(); + ObjectTable currentTableObject = null; + boolean fromCmdLine; + if (args.length == 0) { + fromCmdLine = false; + fillCommandSet(commandSet, currentTableObject, fromCmdLine); + Interpreter interpreter = new Interpreter(commandSet); + interpreter.startUp(null, false); + } else { + fromCmdLine = true; + fillCommandSet(commandSet, currentTableObject, fromCmdLine); + Interpreter interpreter = new Interpreter(commandSet); + String cmd = String.join(" ", args); + cmd = cmd.replaceAll("\\s+", " "); + System.out.println(cmd); + interpreter.startUp(cmd, fromCmdLine); + new Exit().execute(null); + } + } + + private static void fillCommandSet(Set commandSet, ObjectTable currentTableObject, boolean fromCmdLine) { + commandSet.add(new Commit()); + commandSet.add(new Create()); + commandSet.add(new Drop()); + commandSet.add(new Exit()); + commandSet.add(new FillTable()); + commandSet.add(new Get()); + commandSet.add(new List()); + commandSet.add(new MakeDirs()); + commandSet.add(new Put()); + commandSet.add(new Remove()); + commandSet.add(new Rollback()); + commandSet.add(new ShowTables()); + commandSet.add(new Use()); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/CommandTools.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/CommandTools.java new file mode 100644 index 000000000..cd8ebe6c2 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/CommandTools.java @@ -0,0 +1,29 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class CommandTools { + protected static final String DATA_BASE_NAME = System.getProperty("fizteh.db.dir"); + static boolean tableIsChosen = false; + static final int DIR_NUM = 16; + static final int FILE_NUM = 16; + static final String DIR_EXT = ".dir"; + static final String FILE_EXT = ".dat"; + static String usingTableName; + public static final Charset UTF = StandardCharsets.UTF_8; + static ObjectTable currentTable; + public static void informToChooseTable() { + System.err.println("table is not chosen"); + } + + public static boolean amountOfArgumentsIs(int argsAmount, String[] cmd) { + return argsAmount == cmd.length; + } + + public static boolean amountOfArgumentsIsMoreThan(int argsAmount, String[] cmd) { + return argsAmount < cmd.length; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Commit.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Commit.java new file mode 100644 index 000000000..2b91c7451 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Commit.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; + +public class Commit extends Command { + + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(1, cmd)) { + CommandTools.currentTable.commit(); + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "commit"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Create.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Create.java new file mode 100644 index 000000000..9beaeeebb --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Create.java @@ -0,0 +1,66 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; + +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class Create extends Command { + private static final String SPLIT_BY_RIGHT_BRACKET = "\\s*\\)\\s*"; + private static final String SPLIT_BY_LEFT_BRACKET = "\\s*\\(\\s*"; + private static final String SPLIT_BY_SPACE = "\\s+"; + + @Override + public String getCmdName() { + return "create"; + } + + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIsMoreThan(2, cmd)) { + String createParameter; // (...) - type list. + String tableName = cmd[1]; + createParameter = String.join(" ", Arrays.copyOfRange(cmd, 2, cmd.length)); + List> typeList; + try { + typeList = getTypeList(createParameter); + if (typeList != null) { + if (new ObjectTableProvider().createTable(tableName, typeList) != null) { + System.out.println("created"); + } else { + System.out.println(tableName + " exists"); + } + } else { + return false; + } + } catch (IOException e) { + System.err.println(e); + } catch (Exception e) { + System.err.println(e); + } + return true; + } + return false; + } + + public List> getTypeList(String line) { + ObjectTable temp = new ObjectTable(); + List> typeList = new LinkedList<>(); + line = line.replaceAll(SPLIT_BY_RIGHT_BRACKET, ""); + line = line.replaceAll(SPLIT_BY_LEFT_BRACKET, ""); + String[] tmp = line.split(SPLIT_BY_SPACE); + for (String str : tmp) { + Class type = temp.getType(str); + if (type != null) { + typeList.add(type); + } else { + return null; + } + } + return typeList; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Drop.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Drop.java new file mode 100644 index 000000000..4c4e4810d --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Drop.java @@ -0,0 +1,25 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; + +public class Drop extends Command { + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(2, cmd)) { + try { + new ObjectTableProvider().removeTable(cmd[1]); + System.out.println("dropped"); + } catch (Exception e) { + System.err.println(e); + } + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "drop"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Exit.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Exit.java new file mode 100644 index 000000000..384a53ee6 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Exit.java @@ -0,0 +1,36 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; + +public class Exit extends Command { + @Override + public boolean execute(String[] cmd) { + if (CommandTools.currentTable != null && exitAndUseAvailable()) { + new FillTable().execute(null); + } else { + return false; + } + System.exit(0); + return true; + } + + public boolean exitAndUseAvailable() { + if (CommandTools.currentTable != null) { + int uncommitedChanges = CommandTools.currentTable.storage.get().size() + - CommandTools.currentTable.commitStorage.size(); + if (uncommitedChanges == 0 || !CommandTools.tableIsChosen) { + return true; + } + System.out.println(uncommitedChanges + " uncommited changes"); + return false; + } + return true; + } + + @Override + public String getCmdName() { + return "exit"; + } +} + + diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/FillTable.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/FillTable.java new file mode 100644 index 000000000..cb106f4cf --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/FillTable.java @@ -0,0 +1,55 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; + +public class FillTable extends Command { +private final Charset coding = StandardCharsets.UTF_8; + + @Override + public boolean execute(String[] cmd) { + for (Map.Entry entry : CommandTools.currentTable.commitStorage.entrySet()) { + int hashCode = entry.getKey().hashCode(); + Integer nDirectory = hashCode % CommandTools.DIR_NUM; + Integer nFile = hashCode / CommandTools.DIR_NUM % CommandTools.FILE_NUM; + Path fileName = Paths.get(CommandTools.DATA_BASE_NAME, CommandTools.currentTable.getName(), nDirectory + + CommandTools.DIR_EXT); + File file = new File(fileName.toString()); + if (!file.exists()) { + file.mkdir(); + } + fileName = Paths.get(fileName.toString(), nFile + CommandTools.FILE_EXT); + file = new File(fileName.toString()); + try { + if (!file.exists()) { + file.createNewFile(); + } + byte[] bytesKey = (" " + entry.getKey() + " ").getBytes(coding); + DataOutputStream stream = new DataOutputStream(new FileOutputStream(fileName.toString(), true)); + stream.write(bytesKey.length); + stream.write(bytesKey); + byte[] bytesVal = ((" " + entry.getValue().serialisedValue + " ").getBytes(coding)); + stream.write(bytesVal.length - 1); + stream.write(bytesVal); + stream.close(); + } catch (IOException e) { + System.err.println(e); + } + } + return true; + } + + @Override + public String getCmdName() { + return "fill table"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Get.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Get.java new file mode 100644 index 000000000..5beb3e1a4 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Get.java @@ -0,0 +1,33 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; + +public class Get extends Command { + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(2, cmd)) { + try { + if (CommandTools.tableIsChosen) { + ObjectStoreable temp = (ObjectStoreable) CommandTools.currentTable.get(cmd[1]); + if (temp == null) { + System.err.println("not found"); + } else { + System.out.println("found"); + System.out.println(temp.serialisedValue); + } + } else { + CommandTools.informToChooseTable(); + } + } catch (Exception e) { + System.out.println(e); + } + return true; + } + return false; + } + @Override + public String getCmdName() { + return "get"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/List.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/List.java new file mode 100644 index 000000000..5616200ae --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/List.java @@ -0,0 +1,35 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; + +public class List extends Command { + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(1, cmd)) { + if (CommandTools.tableIsChosen) { + java.util.List list = CommandTools.currentTable.list(); + int size = 0; + for (Object iter : list) { + if (size < CommandTools.currentTable.storage.get().size() - 1) { + System.out.print(iter + ", "); + } else { + System.out.print(iter); + } + ++size; + } + if (size != 0) { + System.out.println(); + } + } else { + CommandTools.informToChooseTable(); + } + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "list"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/MakeDirs.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/MakeDirs.java new file mode 100644 index 000000000..5ad7c71be --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/MakeDirs.java @@ -0,0 +1,33 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; + +import java.io.File; + +public class MakeDirs extends Command { + @Override + public boolean execute(String[] cmd) { + File file = new File(CommandTools.DATA_BASE_NAME); + if (!file.exists()) { + file.mkdirs(); + } else { + if (!file.isDirectory()) { + System.err.println(CommandTools.DATA_BASE_NAME + " is not a directory"); + System.exit(1); + } else { + for (File sub : file.listFiles()) { + if (!sub.isDirectory() && !sub.isHidden()) { + System.err.println(CommandTools.DATA_BASE_NAME + File.separator + + sub.getName() + " is not a directory"); + } + } + } + } + return true; + } + + @Override + public String getCmdName() { + return "make"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Put.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Put.java new file mode 100644 index 000000000..52a478ed1 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Put.java @@ -0,0 +1,41 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; + +public class Put extends Command { + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIsMoreThan(2, cmd)) { + if (CommandTools.tableIsChosen) { + String putParameter = new String(); + String key = cmd[1]; + for (int ind = 2; ind < cmd.length; ++ind) { + putParameter += cmd[ind] + " "; + } + putParameter = putParameter.substring(0, putParameter.length() - 1); + try { + ObjectStoreable value = (ObjectStoreable) new ObjectTableProvider(). + deserialize(CommandTools.currentTable, putParameter); + ObjectStoreable temp = (ObjectStoreable) CommandTools.currentTable.put(key, value); + if (temp == null) { + System.out.println("new"); + } else { + System.out.println("overwrite"); + } + } catch (Exception e) { + System.err.println(e); + } + } else { + CommandTools.informToChooseTable(); + } + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "put"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Remove.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Remove.java new file mode 100644 index 000000000..4722e7424 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Remove.java @@ -0,0 +1,32 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; + +public class Remove extends Command { + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(2, cmd)) { + if (CommandTools.tableIsChosen) { + try { + ObjectStoreable temp = (ObjectStoreable) CommandTools.currentTable.remove(cmd[1]); + if (temp == null) { + System.out.println("not found"); + } else { + System.out.println("removed"); + } + } catch (Exception e) { + System.err.println(e); + } + } else { + CommandTools.informToChooseTable(); + } + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "remove"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Rollback.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Rollback.java new file mode 100644 index 000000000..cad06fdb1 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Rollback.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; + +public class Rollback extends Command { + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(1, cmd)) { + CommandTools.currentTable.rollback(); + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "rollback"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/ShowTables.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/ShowTables.java new file mode 100644 index 000000000..d9c56dafc --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/ShowTables.java @@ -0,0 +1,56 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +public class ShowTables extends Command { + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(2, cmd)) { + String currentFile; + int recordsAmount; + File file = new File(CommandTools.DATA_BASE_NAME); + for (File sub : file.listFiles()) { + if ((!sub.isHidden()) && sub.isDirectory()) { + recordsAmount = 0; + for (Integer i = 0; i < CommandTools.DIR_NUM; ++i) { + currentFile = CommandTools.DATA_BASE_NAME + File.separator + sub.getName() + File.separator + i + + CommandTools.DIR_EXT; + File file1 = new File(currentFile); + if (file1.exists()) { + for (Integer j = 0; j < CommandTools.FILE_NUM; ++j) { + currentFile = CommandTools.DATA_BASE_NAME + File.separator + sub.getName() + + File.separator + i + CommandTools.DIR_EXT + File.separator + j + + CommandTools.FILE_EXT; + file1 = new File(currentFile); + try { + if (file1.exists()) { + DataInputStream stream = new DataInputStream(new FileInputStream(currentFile)); + byte[] data = new byte[(int) file1.length()]; + stream.read(data); + String temp = new String(data, StandardCharsets.UTF_8); + recordsAmount += (temp.length() - temp.replaceAll(" ", "").length()) / 4; + } + } catch (FileNotFoundException e) { + System.err.println(e); + } catch (IOException e) { + System.err.println(e); + } + } + } + } + System.out.println(sub.getName() + " " + recordsAmount); + } + } + return true; + } + return false; + } + + @Override + public String getCmdName() { + return "show"; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Use.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Use.java new file mode 100644 index 000000000..2c3ff2df7 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/base/commands/Use.java @@ -0,0 +1,96 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.Command; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; +import java.io.*; +import java.text.ParseException; + +public class Use extends Command { + @Override + public String getCmdName() { + return "use"; + } + + @Override + public boolean execute(String[] cmd) { + if (CommandTools.amountOfArgumentsIs(2, cmd)) { + try { + useFunction(cmd[1], CommandTools.usingTableName); + } catch (IOException e) { + System.err.println(e); + } catch (ParseException e) { + System.err.println(e); + } + return true; + } + return false; + } + + public boolean useFunction(String tableName, String oldTableName) throws IOException, ParseException { + if (!tableName.equals(oldTableName)) { + String outputName = tableName; + String tablePath = CommandTools.DATA_BASE_NAME + File.separator + tableName; + File file = new File(tablePath); + if (file.exists()) { + CommandTools.usingTableName = tableName; + if (CommandTools.tableIsChosen) { + new FillTable().execute(null); + CommandTools.currentTable.storage.get().clear(); + CommandTools.currentTable.commitStorage.clear(); + } + CommandTools.currentTable = new ObjectTable(CommandTools.DATA_BASE_NAME + File.separator + + CommandTools.usingTableName); + for (Integer i = 0; i < CommandTools.DIR_NUM; ++i) { + for (Integer j = 0; j < CommandTools.FILE_NUM; ++j) { + tablePath = CommandTools.DATA_BASE_NAME + File.separator + tableName + File.separator + + i + CommandTools.DIR_EXT + File.separator + j + CommandTools.FILE_EXT; + if (new File(tablePath).exists()) { + fillStorage(tablePath, file); + PrintWriter writer = new PrintWriter(new File(tablePath)); + writer.print(""); + writer.close(); + } + } + } + System.out.println("using " + outputName); + CommandTools.tableIsChosen = true; + } else { + System.err.println(tableName + " not exists"); + return false; + } + } else { + System.out.println("using " + oldTableName); + } + CommandTools.usingTableName = CommandTools.currentTable.getName(); + return true; + } + + void fillStorage(String datName, File file) throws IOException, ParseException { + DataInputStream stream = new DataInputStream(new FileInputStream(datName)); + file = new File(datName); + byte[] data = new byte[(int) file.length()]; + stream.read(data); + int counter = 0; + int offset = 0; + String keyForMap = ""; + String value = ""; + String aLL = new String(data); + while (counter < file.length()) { + offset = data[counter]; + keyForMap = new String(data, counter + 2, offset - 2, CommandTools.UTF); + counter = counter + offset + 1; + offset = data[counter]; + value = new String(data, counter + 2, data.length - counter - 3, CommandTools.UTF); + value = value.replaceAll("^\\s*|\\s*$", ""); + String tableName = new File(new File(datName).getParent()).getParent(); + ObjectStoreable valForMap = (ObjectStoreable) + new ObjectTableProvider().deserialize(new ObjectTable(tableName), value); + CommandTools.currentTable.storage.get().put(keyForMap, valForMap); + CommandTools.currentTable.commitStorage.put(keyForMap, valForMap); + counter = counter + offset + 3; + } + stream.close(); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/interpreter/Command.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/interpreter/Command.java new file mode 100644 index 000000000..f9e2d9f0f --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/interpreter/Command.java @@ -0,0 +1,7 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter; + +public abstract class Command { + public abstract String getCmdName(); + + public abstract boolean execute(String[] cmd); +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/interpreter/Interpreter.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/interpreter/Interpreter.java new file mode 100644 index 000000000..4fc07a2ac --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/interpreter/Interpreter.java @@ -0,0 +1,60 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter; + +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.*; +import java.util.*; + +public class Interpreter { + private static final String SPLIT_BY_SEMICOLON = "\\s*;\\s*"; + private static final String SECRET_TEST_WORD = "extremely_secret_word_for_test"; + private static final String INVITATIONAL_SYMBOL = "$ "; + private static final String SPLIT_BY_SPACE = "\\s+"; + private Map commands = new HashMap<>(); + public Scanner scan = new Scanner(System.in); + + public Interpreter(Set commandSet) { + for (Command cmd: commandSet) { + commands.put(cmd.getCmdName(), cmd); + } + } + + public void startUp(String cmdLine, boolean isFromCmdLine) { + if (isFromCmdLine) { // Batch mode. + String[] splittedLine = cmdLine.split(SPLIT_BY_SEMICOLON); + for (String line : splittedLine) { + String[] cmd = line.split(SPLIT_BY_SPACE); + parseStep(commands, cmd, isFromCmdLine); + } + } else { // Interactive mode. + while (true) { + System.out.print(INVITATIONAL_SYMBOL); + String[] cmd = scan.nextLine().split(SPLIT_BY_SPACE); + if (cmd[0].equals(SECRET_TEST_WORD)) { + break; + } + parseStep(commands, cmd, isFromCmdLine); + } + } + } + + private void parseStep(Map commands, String[] cmd, boolean isFromCmdLine) { + boolean correctCmdName = false; + for (Map.Entry entry : commands.entrySet()) { + String key = entry.getKey(); + if (key.equals(cmd[0])) { + correctCmdName = true; + Command currentCmd = entry.getValue(); + currentCmd.execute(cmd); + break; + } + } + if (!correctCmdName) { + if (!isFromCmdLine) { + System.err.println("no such command, try again..."); + } else { + String[] exit = new String[1]; + exit[0] = "exit"; + new Exit().execute(exit); + } + } + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/Change.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/Change.java new file mode 100644 index 000000000..90488ac63 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/Change.java @@ -0,0 +1,8 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +public abstract class Change { + String key; + String value; + + public abstract void execute(ObjectTable table); +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectStoreable.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectStoreable.java new file mode 100644 index 000000000..0b15b7896 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectStoreable.java @@ -0,0 +1,349 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import java.text.ParseException; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +public class ObjectStoreable implements Storeable { + private static final String LEFT_BRACE = "["; + private static final String RIGHT_BRACE = "]"; + private static final String VALUE_SEPARATOR = ", "; + public List subValueList = new LinkedList<>(); + private static ObjectTable currentTableObject; + public String serialisedValue; + public List> typeKeeper = new LinkedList<>(); + + public ObjectStoreable() {} + + public ObjectStoreable(List values) { + serialisedValue = LEFT_BRACE; + for (Object val : values) { + subValueList.add(val); + serialisedValue += val + VALUE_SEPARATOR; + } + serialisedValue = serialisedValue.substring(0, serialisedValue.length() - 2); + serialisedValue += RIGHT_BRACE; + } + + public ObjectStoreable(ObjectTable table) { + typeKeeper = table.typeKeeper; + } + + public ObjectStoreable(String value) throws ParseException { + ObjectStoreable obj = (ObjectStoreable) new ObjectTableProvider().deserialize(currentTableObject, value); + if (obj == null) { + return; + } + subValueList = obj.subValueList; + serialisedValue = obj.serialisedValue; + typeKeeper = obj.typeKeeper; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.serialisedValue); + } + + @Override + public boolean equals(Object obj) { + ObjectStoreable storeableObj = (ObjectStoreable) obj; + return this.serialisedValue.equals(storeableObj.serialisedValue) + && this.typeKeeper.equals(storeableObj.typeKeeper) + && this.subValueList.equals(storeableObj.subValueList); + } + + @Override + public void setColumnAt(int columnIndex, Object value) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.subValueList.size()) { + throw new IndexOutOfBoundsException(); + } + List> toConvert = new LinkedList<>(); + toConvert.add(value.getClass()); + toConvert = convertToPrimitive(toConvert); + if (!typeKeeper.get(columnIndex).equals(toConvert.get(0))) { + throw new ColumnFormatException(); + } + this.subValueList.set(columnIndex, value); + this.serialisedValue = ""; + serialisedValue = LEFT_BRACE; + for (Object val : this.subValueList) { + serialisedValue += val + VALUE_SEPARATOR; + } + serialisedValue = serialisedValue.substring(0, serialisedValue.length() - 2); + serialisedValue += RIGHT_BRACE; + } + + @Override + public Object getColumnAt(int columnIndex) throws IndexOutOfBoundsException { + if (subValueList.size() < columnIndex - 1) { + throw new IndexOutOfBoundsException(); + } + return subValueList.get(columnIndex); + } + + @Override + public Integer getIntAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= subValueList.size()) { + throw new IndexOutOfBoundsException(); + } + if (!this.typeKeeper.get(columnIndex).equals(int.class)) { + throw new ColumnFormatException(); + } + return (Integer) subValueList.get(columnIndex); + } + + @Override + public Long getLongAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(long.class)) { + throw new ColumnFormatException(); + } + return (Long) subValueList.get(columnIndex); + } + + @Override + public Byte getByteAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(byte.class)) { + throw new ColumnFormatException(); + } + return (Byte) subValueList.get(columnIndex); + } + + @Override + public Float getFloatAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(float.class)) { + throw new ColumnFormatException(); + } + return (Float) subValueList.get(columnIndex); + } + + @Override + public Double getDoubleAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(double.class)) { + throw new ColumnFormatException(); + } + return (Double) subValueList.get(columnIndex); + } + + @Override + public Boolean getBooleanAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(boolean.class)) { + throw new ColumnFormatException(); + } + return (Boolean) subValueList.get(columnIndex); + } + + @Override + public String getStringAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(String.class)) { + throw new ColumnFormatException(); + } + return subValueList.get(columnIndex).toString(); + } + + private List> convertToPrimitive(List> list) { + List> toReturn = new LinkedList<>(); + for (Class object : list) { + if (object.equals(Integer.class)) { + toReturn.add(int.class); + continue; + } + if (object.equals(Long.class)) { + toReturn.add(long.class); + continue; + } + if (object.equals(Boolean.class)) { + toReturn.add(boolean.class); + continue; + } + if (object.equals(String.class)) { + toReturn.add(String.class); + continue; + } + if (object.equals(Byte.class)) { + toReturn.add(byte.class); + continue; + } + if (object.equals(Double.class)) { + toReturn.add(double.class); + continue; + } + if (object.equals(Float.class)) { + toReturn.add(float.class); + continue; + } + } + return toReturn; + } +} + + +/*package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + + import ru.fizteh.fivt.storage.structured.ColumnFormatException; + import ru.fizteh.fivt.storage.structured.Storeable; + import java.text.ParseException; + import java.util.*; + +public class ObjectStoreable implements Storeable { + private static final String LEFT_BRACE = "["; + private static final String RIGHT_BRACE = "]"; + private static final String VALUE_SEPARATOR = ", "; + public List subValueList = new LinkedList<>(); + private static ObjectTable currentTableObject; + public String serialisedValue; + public List> typeKeeper = new LinkedList<>(); + + public ObjectStoreable() {} + + public ObjectStoreable(List values) { + serialisedValue = LEFT_BRACE; + for (Object val : values) { + subValueList.add(val); + } + serialisedValue += String.join(VALUE_SEPARATOR, (List) values); + serialisedValue += RIGHT_BRACE; + } + + public ObjectStoreable(ObjectTable table) { + typeKeeper = table.typeKeeper; + } + + public ObjectStoreable(String value) throws ParseException { + ObjectStoreable obj = (ObjectStoreable) new ObjectTableProvider().deserialize(currentTableObject, value); + if (obj == null) { + return; + } + subValueList = obj.subValueList; + serialisedValue = obj.serialisedValue; + typeKeeper = obj.typeKeeper; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.serialisedValue); + } + + @Override + public boolean equals(Object obj) { + ObjectStoreable storeableObj = (ObjectStoreable) obj; + return this.serialisedValue.equals(storeableObj.serialisedValue) + && this.typeKeeper.equals(storeableObj.typeKeeper) + && this.subValueList.equals(storeableObj.subValueList); + } + + @Override + public void setColumnAt(int columnIndex, Object value) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.subValueList.size()) { + throw new IndexOutOfBoundsException(); + } + List> toConvert = new LinkedList<>(); + toConvert.add(value.getClass()); + toConvert = convertToPrimitive(toConvert); + if (!typeKeeper.get(columnIndex).equals(toConvert.get(0))) { + throw new ColumnFormatException(); + } + this.subValueList.set(columnIndex, value); + this.serialisedValue = ""; + serialisedValue = LEFT_BRACE; + for (Object val : this.subValueList) { + serialisedValue += val + VALUE_SEPARATOR; + } + serialisedValue = serialisedValue.substring(0, serialisedValue.length() - 2); + serialisedValue += RIGHT_BRACE; + } + + @Override + public Object getColumnAt(int columnIndex) throws IndexOutOfBoundsException { + if (subValueList.size() < columnIndex - 1) { + throw new IndexOutOfBoundsException(); + } + return subValueList.get(columnIndex); + } + + @Override + public Integer getIntAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + checkGetSomethingAtException(columnIndex); + return (Integer) subValueList.get(columnIndex); + } + + @Override + public Long getLongAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + checkGetSomethingAtException(columnIndex); + return (Long) subValueList.get(columnIndex); + } + + @Override + public Byte getByteAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + checkGetSomethingAtException(columnIndex); + return (Byte) subValueList.get(columnIndex); + } + + @Override + public Float getFloatAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + checkGetSomethingAtException(columnIndex); + return (Float) subValueList.get(columnIndex); + } + + @Override + public Double getDoubleAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + checkGetSomethingAtException(columnIndex); + return (Double) subValueList.get(columnIndex); + } + + @Override + public Boolean getBooleanAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + checkGetSomethingAtException(columnIndex); + return (Boolean) subValueList.get(columnIndex); + } + + @Override + public String getStringAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(String.class)) { + throw new ColumnFormatException(); + } + return subValueList.get(columnIndex).toString(); + } + + private void checkGetSomethingAtException(int columnIndex) { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(boolean.class)) { + throw new ColumnFormatException(); + } + } + + private List> convertToPrimitive(List> list) { + List> toReturn = new LinkedList<>(); + for (Class object : list) { + toReturn.add(ObjectTableProvider.TYPES_MAP.get(object)); + continue; + } + return toReturn; + } +} +*/ diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTable.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTable.java new file mode 100644 index 000000000..05c87927d --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTable.java @@ -0,0 +1,452 @@ +/*package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.List; + +public class ObjectTable implements Table { + private static int overwriteNum = 0; + private static final String DATA_BASE_NAME = System.getProperty("fizteh.db.dir"); + private static final String SIGNATURE_FILENAME = "signature.tsv"; + + public ThreadLocal lastChanges = new ThreadLocal() { + @Override + protected Stack initialValue() { + return new Stack(); + } + }; + + public ThreadLocal> storage = new ThreadLocal>() { + @Override + protected HashMap initialValue() { + return new HashMap<>(); + } + }; + + public Map commitStorage = new HashMap<>(); + private String tableName = new String(); + public List> typeKeeper = new LinkedList>(); + + public ObjectTable() { } + + public ObjectTable(Table table) { + ObjectTable temp = (ObjectTable) table; + this.tableName = temp.tableName; + this.typeKeeper = temp.typeKeeper; + } + + public ObjectTable(String name) { + if (!new File(name).isAbsolute()) { + name = DATA_BASE_NAME + File.separator + name; + } + this.tableName = new File(name).getName(); + String content; + + if (!new File(name + File.separator + SIGNATURE_FILENAME).isAbsolute()) { + name = DATA_BASE_NAME + File.separator + name; + } + content = readFile(name + File.separator + SIGNATURE_FILENAME, Charset.defaultCharset()); + content = content.replaceAll("\\s+", " "); + String[] types = content.split(" "); + for (String type : types) { + typeKeeper.add(getType(type)); + } + } + + public ObjectTable(String name, List> typeList) { + for (Class type : typeList) { + typeKeeper.add(type); + } + tableName = name; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.tableName); + } + + @Override + public boolean equals(Object obj) { + ObjectTable tableObj = (ObjectTable) obj; + return this.tableName.equals(tableObj.tableName) && this.typeKeeper.equals(tableObj.typeKeeper); + } + + @Override + public String getName() { + return tableName; + } + + @Override + public Storeable get(String key) throws IllegalArgumentException { // В документации в Index + // не сказано, когда кидать ParseException, однако согласно интерфейсу тут все-таки написано + // throws ParseException, но на самом деле это исключение тут не бросатется. + if (key == null) { + throw new IllegalArgumentException(); + } + ObjectStoreable value = storage.get().get(key); + if (value == null) { + return null; + } + return value; + } + + @Override + public Storeable put(String key, Storeable value) throws ColumnFormatException { + if (key == null || value == null) { + throw new IllegalArgumentException(); + } + if (!this.typeKeeper.equals(((ObjectStoreable) value).typeKeeper)) { + throw new ColumnFormatException(); + } + ObjectStoreable previousValue = storage.get().put(key, (ObjectStoreable) value); + if (previousValue == null) { + lastChanges.get().push(key); + lastChanges.get().push("remove"); + } else { + lastChanges.get().push(previousValue); + lastChanges.get().push(key); + lastChanges.get().push("put"); + ++overwriteNum; + } + return previousValue; + } + + @Override + public Storeable remove(String key) { + if (key == null) { + throw new IllegalArgumentException(); + } + ObjectStoreable value = storage.get().remove(key); + commitStorage.remove(key); + if (value != null) { + lastChanges.get().push(value); + lastChanges.get().push(key); + lastChanges.get().push("put"); + } + return value; + } + + @Override + public int size() { + return storage.get().size(); + } + + @Override + public List list() { + LinkedList list = new LinkedList(); + Set k = storage.get().keySet(); + for (Object iter : k) { + list.add(iter.toString()); + } + return list; + } + + @Override + public int commit() { + int savedKeys = Math.abs(storage.get().size() - commitStorage.size()); + commitStorage = new HashMap<>(storage.get()); + lastChanges.get().clear(); + return savedKeys; + } + + @Override + public int rollback() throws IllegalArgumentException { + int changes = Math.abs(storage.get().size() - commitStorage.size() + overwriteNum); + while (!lastChanges.get().isEmpty()) { + Object tmpCmd = lastChanges.get().pop(); + if (tmpCmd.equals("put")) { + String key = lastChanges.get().pop().toString(); + ObjectStoreable value = (ObjectStoreable) lastChanges.get().pop(); + storage.get().put(key, value); + } + if (tmpCmd.equals("remove")) { + String key = lastChanges.get().pop().toString(); + storage.get().remove(key); + } + } + overwriteNum = 0; + return changes; + } + + @Override + public int getNumberOfUncommittedChanges() { + int numberOfUncommitedChanges = Math.abs(storage.get().size() - commitStorage.size()); + return numberOfUncommitedChanges; + } + + @Override + public int getColumnsCount() { + return typeKeeper.size(); + } + + @Override + public Class getColumnType(int columnIndex) throws IndexOutOfBoundsException { + if (this.getColumnsCount() < columnIndex - 1) { + throw new IndexOutOfBoundsException(); + } + Class objectToReturn = typeKeeper.get(columnIndex); + return objectToReturn; + } + + private static String readFile(String path, Charset encoding) { + byte[] encoded; + try { + encoded = Files.readAllBytes(Paths.get(path)); + String temp = new String(encoded, encoding); + return temp.replaceAll("^\\s*|\\s*$", ""); + } catch (IOException e) { + return null; + } + } + + public Class getType(String typeName) { + if (typeName.equals("int")) { + return int.class; + } + if (typeName.equals("long")) { + return long.class; + } + if (typeName.equals("byte")) { + return byte.class; + } + if (typeName.equals("float")) { + return float.class; + } + if (typeName.equals("double")) { + return double.class; + } + if (typeName.equals("boolean")) { + return boolean.class; + } + if (typeName.equals("String")) { + return String.class; + } + return null; + } +} + +*/ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.List; + +public class ObjectTable implements Table { + private int overwriteNum = 0; + + public ThreadLocal lastChanges = new ThreadLocal() { + @Override + protected Stack initialValue() { + return new Stack(); + } + }; + + public ThreadLocal> storage = new ThreadLocal>() { + @Override + protected HashMap initialValue() { + return new HashMap<>(); + } + }; + + public Map commitStorage = new HashMap<>(); + public String tableName = new String(); + public List> typeKeeper = new LinkedList<>(); + + public ObjectTable() { } + + public ObjectTable(Table table) { + ObjectTable temp = (ObjectTable) table; + this.tableName = temp.tableName; + this.typeKeeper = temp.typeKeeper; + } + + public ObjectTable(String name) { + if (!new File(name).isAbsolute()) { + name = ObjectTableProvider.dataBaseName + File.separator + name; + } + this.tableName = new File(name).getName(); + if (!new File(name + File.separator + ObjectTableProvider.SIGNATURE_FILENAME).isAbsolute()) { + name = ObjectTableProvider.dataBaseName + File.separator + name; + } + String content = readFile(name + File.separator + ObjectTableProvider.SIGNATURE_FILENAME, + Charset.defaultCharset()); + content = content.replaceAll("\\s+", " "); + String[] types = content.split(" "); + for (String type : types) { + typeKeeper.add(getType(type)); + } + } + + public ObjectTable(String name, List> typeList) { + for (Class type : typeList) { + typeKeeper.add(type); + } + tableName = name; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.tableName); + } + + @Override + public boolean equals(Object obj) { + return (this.tableName.equals(((ObjectTable) obj).tableName) + && this.typeKeeper.equals(((ObjectTable) obj).typeKeeper)); + } + + @Override + public String getName() { + return tableName; + } + + @Override + public Storeable get(String key) throws IllegalArgumentException { // В документации в Index + // не сказано, когда кидать ParseException, однако согласно интерфейсу тут все-таки написано + // throws ParseException, но на самом деле это исключение тут не бросатется. + if (key == null) { + throw new IllegalArgumentException(); + } + ObjectStoreable value = storage.get().get(key); + if (value == null) { + return null; + } + return value; + } + + @Override + public Storeable put(String key, Storeable value) throws ColumnFormatException { + if (key == null || value == null) { + throw new IllegalArgumentException(); + } + if (!this.typeKeeper.equals(((ObjectStoreable) value).typeKeeper)) { + throw new ColumnFormatException(); + } + ObjectStoreable previousValue = storage.get().put(key, (ObjectStoreable) value); + if (previousValue == null) { + lastChanges.get().push(new RemoveChange(key)); + } else { + lastChanges.get().push(new PutChange(key, previousValue)); + ++overwriteNum; + } + return previousValue; + } + + @Override + public Storeable remove(String key) { + if (key == null) { + throw new IllegalArgumentException(); + } + ObjectStoreable value = storage.get().remove(key); + commitStorage.remove(key); + if (value != null) { + lastChanges.get().push(new PutChange(key, value)); + } + return value; + } + + @Override + public int size() { + return storage.get().size(); + } + + @Override + public List list() { + LinkedList list = new LinkedList(); + Set k = storage.get().keySet(); + for (Object iter : k) { + list.add(iter.toString()); + } + return list; + } + + @Override + public int commit() { + int savedKeys = Math.abs(storage.get().size() - commitStorage.size()); + commitStorage = new HashMap<>(storage.get()); + lastChanges.get().clear(); + return savedKeys; + } + + @Override + public int rollback() throws IllegalArgumentException { + int changes = Math.abs(storage.get().size() - commitStorage.size() + overwriteNum); + while (!lastChanges.get().isEmpty()) { + ((Change) lastChanges.get().pop()).execute(this); + } + overwriteNum = 0; + return changes; + } + + @Override + public int getNumberOfUncommittedChanges() { + int numberOfUncommitedChanges = Math.abs(storage.get().size() - commitStorage.size()); + return numberOfUncommitedChanges; + } + + @Override + public int getColumnsCount() { + return typeKeeper.size(); + } + + @Override + public Class getColumnType(int columnIndex) throws IndexOutOfBoundsException { + if (this.getColumnsCount() < columnIndex - 1) { + throw new IndexOutOfBoundsException(); + } + Class objectToReturn = typeKeeper.get(columnIndex); + return objectToReturn; + } + + static String readFile(String path, Charset encoding) { + try { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + + String temp = new String(encoded, encoding); + return temp.replaceAll("^\\s*|\\s*$", ""); + } catch (IOException e) { + return null; + } + } + + public Class getType(String typeName) { + if (typeName.equals("int")) { + return int.class; + } + if (typeName.equals("long")) { + return long.class; + } + if (typeName.equals("byte")) { + return byte.class; + } + if (typeName.equals("float")) { + return float.class; + } + if (typeName.equals("double")) { + return double.class; + } + if (typeName.equals("boolean")) { + return boolean.class; + } + if (typeName.equals("String")) { + return String.class; + } + return null; + } +} + diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTableProvider.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTableProvider.java new file mode 100644 index 000000000..4c0c0f3a9 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTableProvider.java @@ -0,0 +1,650 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.*; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.storage.structured.TableProvider; +import java.io.*; +import java.text.ParseException; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ObjectTableProvider implements TableProvider { + private static final String INCORRECT_SYMBOL = "^incorrect@"; + private static final String BRACES_KILLER = "^\\s*\\[\\s*|\\s*\\]\\s*$"; + private static final int LONGEST_NAME = 260; + private static final String JSON_REG_EX = "\\s*,\\s*(?=(?:(?:[^\"]*\"){2})*[^\"]*$)"; + public static String usingTableName; + public static ObjectTable currentTableObject; + static final String SIGNATURE_FILENAME = "signature.tsv"; + private static Boolean tableIsChosen = false; + public static String dataBaseName = System.getProperty("fizteh.db.dir"); + private volatile boolean writeSectionIsInUse = false; + private String rootDirectory = ""; + public ObjectTableProvider() { + rootDirectory = dataBaseName; + } + + public ObjectTableProvider(String dir) { + dataBaseName = dir; + rootDirectory = dir; + } + + public int hashCode() { + return Objects.hashCode(this.rootDirectory); + } + + @Override + public boolean equals(Object obj) { + ObjectTableProvider tempObj = (ObjectTableProvider) obj; + return tempObj.rootDirectory.equals(this.rootDirectory); + } + @Override + public Table getTable(String name) throws IllegalArgumentException { + checkException(name); + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + String tempPath = rootDirectory + File.separator + name; + if (new File(tempPath).exists()) { + readWriteLock.readLock().lock(); + ObjectTable tableToReturn = new ObjectTable(tempPath); + readWriteLock.readLock().unlock(); + return tableToReturn; + } + return null; + } + @Override + public Table createTable(String name, List> columnTypes) throws IOException, IllegalArgumentException { + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + if (writeSectionIsInUse) { + return null; + } + writeSectionIsInUse = true; + readWriteLock.writeLock().lock(); + checkException(name); + File file = new File(rootDirectory + File.separator + name); + File signatureFile = new File(rootDirectory + File.separator + name + File.separator + SIGNATURE_FILENAME); + if (file.exists()) { + return null; + } else { + file.mkdir(); + signatureFile.createNewFile(); + PrintWriter writer = new PrintWriter(signatureFile, CommandTools.UTF.toString()); + String tempTypes = new String(); + for (Class type : columnTypes) { + if (type.equals(String.class)) { + tempTypes += "String "; + } else { + tempTypes += type.getName() + " "; + } + } + tempTypes = tempTypes.substring(0, tempTypes.length() - 1); + writer.println(tempTypes); + writer.close(); + } + readWriteLock.writeLock().unlock(); + writeSectionIsInUse = false; + return new ObjectTable(name, columnTypes); + } + @Override + public void removeTable(String name) throws IllegalArgumentException, IllegalStateException { + if (name == null || name.length() > LONGEST_NAME) { + throw new IllegalArgumentException(); + } + String tableName = rootDirectory + File.separator + name; + File toBeRemoved = new File(tableName); + if (toBeRemoved.exists()) { + if (tableIsChosen) { + if (usingTableName.equals(name)) { + currentTableObject.storage.get().clear(); + currentTableObject.commitStorage.clear(); + tableIsChosen = false; + usingTableName = null; + } + } + recRem(tableName); + toBeRemoved.delete(); + } else { + throw new IllegalStateException(); + } + } + + @Override + public Storeable deserialize(Table table, String value) throws ParseException { + ObjectTable usingTable = (ObjectTable) table; + ObjectStoreable valueToReturn = new ObjectStoreable(); + String[] splittedValue = value.split(""); + if (!splittedValue[0].equals("[") || !splittedValue[splittedValue.length - 1].equals("]")) { + throw new ParseException(value, 0); + } + valueToReturn.serialisedValue = value; + value = value.replaceAll(BRACES_KILLER, ""); // Removing [ and ]. + String[] tempValue = value.split(JSON_REG_EX); // Split by comma. + if (usingTable.getColumnsCount() != tempValue.length) { + throw new ParseException(value, 0); + } + int index = 0; + List> typeList = new LinkedList<>(); + for (String str : tempValue) { + Object val = getValue(str, usingTable.typeKeeper.get(index)); + if (val.equals(INCORRECT_SYMBOL)) { + throw new ParseException(value, 0); + } + valueToReturn.subValueList.add(val); + typeList.add(val.getClass()); + ++index; + } + valueToReturn.typeKeeper = usingTable.typeKeeper; + return valueToReturn; + } + + @Override + public String serialize(Table table, Storeable value) throws ColumnFormatException { + ObjectStoreable valueToSerialize = (ObjectStoreable) value; + ObjectTable tableObj = (ObjectTable) table; + int index = 0; + for (Class type : tableObj.typeKeeper) { + if (!type.equals(valueToSerialize.typeKeeper.get(index))) { + throw new ColumnFormatException(); + } + ++index; + } + return valueToSerialize.serialisedValue; + } + + @Override + public Storeable createFor(Table table) { + return new ObjectStoreable((ObjectTable) table); + } + + @Override + public Storeable createFor(Table table, List values) throws ColumnFormatException, IndexOutOfBoundsException { + ObjectTable tempTable = new ObjectTable(table); + List> valTypes; + valTypes = convertToPrimitive(values); + if (values.size() != tempTable.getColumnsCount()) { + throw new IndexOutOfBoundsException(); + } + if (!valTypes.equals(tempTable.typeKeeper)) { + throw new ColumnFormatException(); + } + ObjectStoreable toReturn = new ObjectStoreable(values); + toReturn.typeKeeper = tempTable.typeKeeper; + return toReturn; + } + + @Override + public List getTableNames() { + List list = new LinkedList<>(); + File file = new File(rootDirectory); + for (File sub : file.listFiles()) { + if ((!sub.isHidden()) && sub.isDirectory()) { + list.add(sub.getName()); + } + } + return list; + } + + private Object getValue(String str, Class expectedType) + throws NumberFormatException { + if (expectedType.equals(int.class)) { + if (isNull(str)) { + return null; + } + Integer toReturn = Integer.parseInt(str); + return toReturn; + } + if (expectedType.equals(long.class)) { + if (isNull(str)) { + return null; + } + Long toReturn = Long.parseLong(str); + return toReturn; + } + if (expectedType.equals(boolean.class)) { + if (isNull(str)) { + return null; + } + Boolean toReturn = Boolean.parseBoolean(str); + return toReturn; + } + if (expectedType.equals(String.class)) { + if (isNull(str)) { + return null; + } + String[] tmp = str.split(""); + if (tmp[0].equals("\"") && tmp[tmp.length - 1].equals("\"")) { + return str; + } else { + throw new NumberFormatException(); + } + } + if (expectedType.equals(byte.class)) { + if (isNull(str)) { + return null; + } + Byte toReturn = Byte.parseByte(str); + return toReturn; + } + if (expectedType.equals(double.class)) { + if (isNull(str)) { + return null; + } + Double toReturn = Double.parseDouble(str); + return toReturn; + } + if (expectedType.equals(float.class)) { + if (isNull(str)) { + return null; + } + Float toReturn = Float.parseFloat(str); + return toReturn; + } + return INCORRECT_SYMBOL; + } + + boolean isNull(String str) { + if (str.equals("null")) { + return true; + } + return false; + } + + private void recRem(String myFile) { + File file = new File(myFile); + if (!file.exists()) { + return; + } + if (file.isDirectory()) { + for (File f : file.listFiles()) { + recRem(f.getAbsolutePath()); + } + } + file.delete(); + } + + public void checkException(String name) throws IllegalArgumentException { + if (name == null || name.length() > LONGEST_NAME) { + throw new IllegalArgumentException(); + } + } + + private List> convertToPrimitive(List list) { + List> toReturn = new LinkedList>(); + for (Object object : list) { + if (object.getClass().equals(Integer.class)) { + toReturn.add(int.class); + continue; + } + if (object.getClass().equals(Long.class)) { + toReturn.add(long.class); + continue; + } + if (object.getClass().equals(Boolean.class)) { + toReturn.add(boolean.class); + continue; + } + if (object.getClass().equals(String.class)) { + toReturn.add(String.class); + continue; + } + if (object.getClass().equals(Byte.class)) { + toReturn.add(byte.class); + continue; + } + if (object.getClass().equals(Double.class)) { + toReturn.add(double.class); + continue; + } + if (object.getClass().equals(Float.class)) { + toReturn.add(float.class); + continue; + } + } + return toReturn; + } +} + +/* +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + + import ru.fizteh.fivt.storage.structured.ColumnFormatException; + import ru.fizteh.fivt.storage.structured.Storeable; + import ru.fizteh.fivt.storage.structured.Table; + import ru.fizteh.fivt.storage.structured.TableProvider; + import java.io.*; + import java.nio.charset.StandardCharsets; + import java.text.ParseException; + import java.util.*; + import java.util.concurrent.locks.ReadWriteLock; + import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ObjectTableProvider implements TableProvider { + static final Map, Class> TYPES_MAP = new HashMap, Class>() { + { + TYPES_MAP.put(int.class, int.class); + TYPES_MAP.put(long.class, long.class); + TYPES_MAP.put(byte.class, byte.class); + TYPES_MAP.put(float.class, float.class); + TYPES_MAP.put(double.class, double.class); + TYPES_MAP.put(boolean.class, boolean.class); + TYPES_MAP.put(String.class, String.class); + } + }; + private static final String BRACES_KILLER = "^\\s*\\[\\s*|\\s*\\]\\s*$"; + public static final String FILE_EXT = ".dat"; + public static final Integer FILE_NUM = 16; + public static final String DIR_EXT = ".dir"; + public static final Integer DIR_NUM = 16; + private static final String JSON_REG_EX = "\\s*,\\s*(?=(?:(?:[^\"]*\"){2})*[^\"]*$)"; + public static String usingTableName; + public static ObjectTable currentTableObject; + static final String SIGNATURE_FILENAME = "signature.tsv"; + private static Boolean tableIsChosen = false; + public static String dataBaseName = System.getProperty("fizteh.db.dir"); + private volatile boolean writeSectionIsInUse = false; + private String rootDirectory = ""; + + public ObjectTableProvider() { + rootDirectory = dataBaseName; + } + + public ObjectTableProvider(String dir) { + dataBaseName = dir; + rootDirectory = dir; + } + + public int hashCode() { + return Objects.hashCode(this.rootDirectory); + } + + @Override + public boolean equals(Object obj) { + ObjectTableProvider tempObj = (ObjectTableProvider) obj; + return tempObj.rootDirectory.equals(this.rootDirectory); + } + @Override + public Table getTable(String name) throws IllegalArgumentException { + checkException(name); + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + if (new File(rootDirectory + File.separator + name).exists()) { + readWriteLock.readLock().lock(); + ObjectTable tableToReturn; + try { + tableToReturn = new ObjectTable(rootDirectory + File.separator + name); + } catch (IOException e) { + return null; + } + readWriteLock.readLock().unlock(); + return tableToReturn; + } + return null; + } + @Override + public Table createTable(String name, List> columnTypes) throws IOException, IllegalArgumentException { + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + if (writeSectionIsInUse) { + return null; + } + writeSectionIsInUse = true; + readWriteLock.writeLock().lock(); + checkException(name); + File file = new File(rootDirectory + File.separator + name); + File signatureFile = new File(rootDirectory + File.separator + name + File.separator + SIGNATURE_FILENAME); + if (file.exists()) { + readWriteLock.writeLock().unlock(); + return new ObjectTable(name, columnTypes); + } else { + file.mkdir(); + signatureFile.createNewFile(); + PrintWriter writer = new PrintWriter(signatureFile, "UTF-8"); + String tempTypes = new String(); + for (Class type : columnTypes) { + if (type.equals(String.class)) { + tempTypes += "String "; + } else { + tempTypes += type.getName() + " "; + } + } + tempTypes = tempTypes.substring(0, tempTypes.length() - 1); + writer.println(tempTypes); + writer.close(); + System.out.println("created"); + } + writeSectionIsInUse = false; + return new ObjectTable(name, columnTypes); + } + @Override + public void removeTable(String name) throws IllegalArgumentException, IllegalStateException { + if (name == null || name.length() > ObjectTableProviderFactory.LONGEST_NAME) { + throw new IllegalArgumentException(); + } + String tableName = rootDirectory + File.separator + name; + File toBeRemoved = new File(tableName); + if (toBeRemoved.exists()) { + if (tableIsChosen) { + if (usingTableName.equals(name)) { + currentTableObject.storage.get().clear(); + currentTableObject.commitStorage.clear(); + tableIsChosen = false; + usingTableName = null; + } + } + recRem(tableName); + toBeRemoved.delete(); + System.out.println("dropped"); + } else { + throw new IllegalStateException(); + } + } + + @Override + public Storeable deserialize(Table table, String value) throws ParseException { + ObjectTable usingTable = (ObjectTable) table; + ObjectStoreable valueToReturn = new ObjectStoreable(); + String[] splittedValue = value.split(""); + if (!splittedValue[0].equals("[") || !splittedValue[splittedValue.length - 1].equals("]")) { + throw new ParseException(value, 0); + } + valueToReturn.serialisedValue = value; + value = value.replaceAll(BRACES_KILLER, ""); // Removing [ and ]. + String[] tempValue = value.split(JSON_REG_EX); // Split by comma. + if (usingTable.getColumnsCount() != tempValue.length) { + throw new ParseException(value, 0); + } + int index = 0; + List> typeList = new LinkedList<>(); + for (String str : tempValue) { + Object val = getValue(str, usingTable, usingTable.typeKeeper.get(index)); + if (val.equals("^incorrect$")) { + throw new ParseException(value, 0); + } + valueToReturn.subValueList.add(val); + typeList.add(val.getClass()); + ++index; + } + valueToReturn.typeKeeper = usingTable.typeKeeper; + return valueToReturn; + } + + @Override + public String serialize(Table table, Storeable value) throws ColumnFormatException { + ObjectStoreable valueToSerialize = (ObjectStoreable) value; + ObjectTable tableObj = (ObjectTable) table; + int index = 0; + for (Class type : tableObj.typeKeeper) { + if (!type.equals(valueToSerialize.typeKeeper.get(index))) { + throw new ColumnFormatException(); + } + ++index; + } + return valueToSerialize.serialisedValue; + } + + @Override + public Storeable createFor(Table table) { + return new ObjectStoreable((ObjectTable) table); + } + + @Override + public Storeable createFor(Table table, List values) throws ColumnFormatException, IndexOutOfBoundsException { + int ind = 0; + ObjectTable tempTable = new ObjectTable(table); + List> valTypes = new LinkedList>(); + valTypes = convertToPrimitive(values); + if (values.size() != tempTable.getColumnsCount()) { + throw new IndexOutOfBoundsException(); + } + if (!valTypes.equals(tempTable.typeKeeper)) { + throw new ColumnFormatException(); + } + ObjectStoreable toReturn = new ObjectStoreable(values); + toReturn.typeKeeper = tempTable.typeKeeper; + return toReturn; + } + + @Override + public List getTableNames() { + List list = new LinkedList(); + String currentFile = new String(); + int recordsAmount = 0; + File file = new File(rootDirectory); + for (File sub : file.listFiles()) { + if ((!sub.isHidden()) && sub.isDirectory()) { + recordsAmount = 0; + for (Integer i = 0; i < DIR_NUM; ++i) { + currentFile = rootDirectory + File.separator + sub.getName() + File.separator + + i + DIR_EXT; + File file1 = new File(currentFile); + if (file1.exists()) { + for (Integer j = 0; j < FILE_NUM; ++j) { + currentFile = rootDirectory + File.separator + sub.getName() + File.separator + + i + DIR_EXT + File.separator + j + FILE_EXT; + file1 = new File(currentFile); + try { + if (file1.exists()) { + DataInputStream stream = new DataInputStream(new FileInputStream(currentFile)); + byte[] data = new byte[(int) file1.length()]; + stream.read(data); + String temp = new String(data, StandardCharsets.UTF_8); + recordsAmount += (temp.length() - temp.replaceAll(" ", "").length()) / 4; + } + } catch (FileNotFoundException e) { + return null; + } catch (IOException e) { + return null; + } + } + } + } + currentFile = new File(new File(new File(currentFile).getParent()).getParent()).getName(); + list.add(sub.getName()); + if (sub.getName().equals(usingTableName)) { + System.out.println(sub.getName() + " " + + (recordsAmount + currentTableObject.storage.get().size())); + } else { + System.out.println(sub.getName() + " " + recordsAmount); + } + } + } + return list; + } + + private Object getValue(String str, ObjectTable usingTable, Class expectedType) throws NumberFormatException { + for (Class type : usingTable.typeKeeper) { + if (expectedType.equals(int.class)) { + if (str.equals("null")) { + return null; + } + Integer toReturn = Integer.parseInt(str); + return toReturn; + } + if (expectedType.equals(long.class)) { + if (str.equals("null")) { + return null; + } + Long toReturn = Long.parseLong(str); + return toReturn; + } + if (expectedType.equals(boolean.class)) { + if (str.equals("null")) { + return null; + } + Boolean toReturn = Boolean.parseBoolean(str); + return toReturn; + } + if (expectedType.equals(String.class)) { + if (str.equals("null")) { + return null; + } + String[] tmp = str.split(""); + if (tmp[0].equals("\"") && tmp[tmp.length - 1].equals("\"")) { + return str; + } else { + throw new NumberFormatException(); + } + } + if (expectedType.equals(byte.class)) { + if (str.equals("null")) { + return null; + } + Byte toReturn = Byte.parseByte(str); + return toReturn; + } + if (expectedType.equals(double.class)) { + if (str.equals("null")) { + return null; + } + Double toReturn = Double.parseDouble(str); + return toReturn; + } + if (expectedType.equals(float.class)) { + if (str.equals("null")) { + return null; + } + Float toReturn = Float.parseFloat(str); + return toReturn; + } + } + return "^incorrect@"; + } + + void recRem(String myFile) { + File file = new File(myFile); + if (!file.exists()) { + return; + } + if (file.isDirectory()) { + for (File f : file.listFiles()) { + recRem(f.getAbsolutePath()); + } + } + file.delete(); + } + + public void checkException(String name) throws IllegalArgumentException { + if (name == null || name.length() > ObjectTableProviderFactory.LONGEST_NAME) { + throw new IllegalArgumentException(); + } + } + + private List> convertToPrimitive(List list) { + List> toReturn = new LinkedList>(); + for (Object object : list) { + toReturn.add(TYPES_MAP.get(object)); + continue; + } + return toReturn; + } + + private void initialization() { + tableIsChosen = false; + dataBaseName = System.getProperty("fizteh.db.dir"); + writeSectionIsInUse = false; + rootDirectory = ""; + } +} +*/ diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTableProviderFactory.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTableProviderFactory.java new file mode 100644 index 000000000..c24b9919a --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/ObjectTableProviderFactory.java @@ -0,0 +1,44 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; + +public class ObjectTableProviderFactory implements TableProviderFactory { + private static final int LONGEST_NAME = 260; + String dirName; + + @Override + public TableProvider create(String dir) throws IllegalArgumentException { + dirName = dir; + if (dir == null || dir.length() > LONGEST_NAME) { + throw new IllegalArgumentException(); + } + return new ObjectTableProvider(dir); + } +} + +/* +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; + +public class ObjectTableProviderFactory implements TableProviderFactory { + static final int LONGEST_NAME = 260; + String dirName; + + @Override + public TableProvider create(String dir) throws IllegalArgumentException { + dirName = dir; + try { + if (dir == null || dir.length() > LONGEST_NAME) { + throw new IllegalArgumentException(); + } + } catch (IllegalArgumentException s) { + System.err.println(s); + return null; + } + return new ObjectTableProvider(dir); + } +} +*/ diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/PutChange.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/PutChange.java new file mode 100644 index 000000000..6647de773 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/PutChange.java @@ -0,0 +1,16 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +public class PutChange extends Change { + String key; + ObjectStoreable value; + + public PutChange(String keyParam, ObjectStoreable valueParam) { + key = keyParam; + value = valueParam; + } + + @Override + public void execute(ObjectTable table) { + table.storage.get().put(key, value); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/RemoveChange.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/RemoveChange.java new file mode 100644 index 000000000..2fd5d387f --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/objects/RemoveChange.java @@ -0,0 +1,13 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects; + +public class RemoveChange extends Change { + String key; + public RemoveChange(String keyParam) { + key = keyParam; + } + + @Override + public void execute(ObjectTable table) { + table.storage.get().remove(key); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/InterpreterTest/BatchModeTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/InterpreterTest/BatchModeTest.java new file mode 100644 index 000000000..74923d286 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/InterpreterTest/BatchModeTest.java @@ -0,0 +1,165 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.test.InterpreterTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.List; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.*; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class BatchModeTest { + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private Set commandSet; + private Interpreter interpreter; + private ObjectTableProvider testTableProvider = new ObjectTableProvider(); + private static final String TEST_TABLE_NAME = "test_table"; + + @Before + public void setUpStreams() throws IOException { + commandSet = new HashSet<>(); + commandSet.add(new Commit()); + commandSet.add(new Create()); + commandSet.add(new Drop()); + commandSet.add(new Exit()); + commandSet.add(new FillTable()); + commandSet.add(new Get()); + commandSet.add(new List()); + commandSet.add(new MakeDirs()); + commandSet.add(new Put()); + commandSet.add(new Remove()); + commandSet.add(new Rollback()); + commandSet.add(new ShowTables()); + commandSet.add(new Use()); + interpreter = new Interpreter(commandSet); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + java.util.List> types = new LinkedList<>(); + types.add(int.class); + testTableProvider.createTable(TEST_TABLE_NAME, types); + } + + @Test + public void useTest() { + String[] cmd = {"use", TEST_TABLE_NAME}; + assertTrue(new Use().execute(cmd)); + } + + @Test + public void useErrTest() { + String[] cmd = {"bugaga"}; + assertFalse(new Use().execute(cmd)); + } + + @Test + public void showTablesTest() { + String[] cmd = {"show", "tables"}; + assertTrue(new ShowTables().execute(cmd)); + } + + @Test + public void showTablesErrTest() { + String[] cmd = {"bugaga"}; + assertFalse(new ShowTables().execute(cmd)); + } + + @Test + public void rollbackTest() { + String[] cmd = {"rollback"}; + assertTrue(new Rollback().execute(cmd)); + } + + @Test + public void rollbackErrTest() { + String[] cmd = {"bugaga", "fail"}; + assertFalse(new Rollback().execute(cmd)); + } + + @Test + public void removeTest() { + String[] cmd = {"remove", "not_existing_table"}; + assertTrue(new Remove().execute(cmd)); + } + + @Test + public void removeErrTest() { + String[] cmd = {"bugaga"}; + assertFalse(new Remove().execute(cmd)); + } + + @Test + public void putTest() { + String[] cmd = {"put", "K", "[100]"}; + assertTrue(new Put().execute(cmd)); + } + + @Test + public void putErrTest() { + String[] cmd = {"bugaga"}; + assertFalse(new Put().execute(cmd)); + } + + @Test + public void listTest() { + String[] cmd = {"list"}; + assertTrue(new List().execute(cmd)); + } + + @Test + public void listErrTest() { + String[] cmd = {"bugaga", "fail"}; + assertFalse(new List().execute(cmd)); + } + + @Test + public void dropTest() { + String[] cmd = {"drop", "something"}; + assertTrue(new Drop().execute(cmd)); + } + + @Test + public void dropErrTest() { + String[] cmd = {"bugaga"}; + assertFalse(new Drop().execute(cmd)); + } + + @Test + public void createTest() { + String[] cmd = {"create", "something", "(int)"}; + assertTrue(new Create().execute(cmd)); + } + + @Test + public void createErrTest() { + String[] cmd = {"bugaga"}; + assertFalse(new Create().execute(cmd)); + } + + @Test + public void commitTest() { + String[] cmd = {"commit"}; + assertTrue(new Commit().execute(cmd)); + } + + @Test + public void commitErrTest() { + String[] cmd = {"bugaga", "fail"}; + assertFalse(new Commit().execute(cmd)); + } + + @After + public void cleanUpStreams() { + System.setOut(null); + System.setErr(null); + testTableProvider.removeTable(TEST_TABLE_NAME); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/InterpreterTest/InteractiveModeTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/InterpreterTest/InteractiveModeTest.java new file mode 100644 index 000000000..959b4a4fb --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/InterpreterTest/InteractiveModeTest.java @@ -0,0 +1,162 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.test.InterpreterTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.List; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.interpreter.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class InteractiveModeTest { + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private Set commandSet; + private Interpreter interpreter; + private ObjectTableProvider testTableProvider = new ObjectTableProvider(); + private static final String TEST_TABLE_NAME = "test_table"; + + @Before + public void setUpStreams() throws IOException { + commandSet = new HashSet<>(); + commandSet.add(new Commit()); + commandSet.add(new Create()); + commandSet.add(new Drop()); + commandSet.add(new Exit()); + commandSet.add(new FillTable()); + commandSet.add(new Get()); + commandSet.add(new List()); + commandSet.add(new MakeDirs()); + commandSet.add(new Put()); + commandSet.add(new Remove()); + commandSet.add(new Rollback()); + commandSet.add(new ShowTables()); + commandSet.add(new Use()); + interpreter = new Interpreter(commandSet); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + java.util.List> types = new LinkedList<>(); + types.add(int.class); + testTableProvider.createTable(TEST_TABLE_NAME, types); + } + + @Test + public void dollarBillTest() { + ByteArrayInputStream in = new ByteArrayInputStream("extremely_secret_word_for_test".getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ ", outContent.toString()); + } + + @Test + public void createAndDropTableTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("create " + TEST_TABLE_NAME + " (int)\n" + + "extremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ " + TEST_TABLE_NAME + " exists\n$ ", outContent.toString()); + in = new ByteArrayInputStream(("create to_be_dropped (long)\n" + + "extremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ " + TEST_TABLE_NAME + " exists\n$ $ created\n$ ", outContent.toString()); + in = new ByteArrayInputStream(("drop to_be_dropped\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ " + TEST_TABLE_NAME + " exists\n$ $ created\n$ $ dropped\n$ ", outContent.toString()); + } + + @Test + public void putAndGetTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("use " + TEST_TABLE_NAME + "\nput K [100500]\n" + + "extremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ new\n$ ", outContent.toString()); + in = new ByteArrayInputStream(("get K\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ new\n$ $ found\n[100500]\n$ ", outContent.toString()); + } + + @Test + public void listTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("use " + TEST_TABLE_NAME + "\nput K [100500]\nlist\n" + + "extremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ new\n$ K\n$ ", outContent.toString()); + } + + @Test + public void removeTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("use " + TEST_TABLE_NAME + "\nput K [100500]\n" + + "remove K\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ new\n$ removed\n$ ", outContent.toString()); + in = new ByteArrayInputStream(("remove K\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ new\n$ removed\n$ $ not found\n$ ", outContent.toString()); + } + + @Test + public void rollbackTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("use " + TEST_TABLE_NAME + "\nput K [10050]\n" + + "rollback\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ overwrite\n$ $ ", outContent.toString()); + } + + @Test + public void showTablesTest() { // Use empty dir. + ByteArrayInputStream in = new ByteArrayInputStream(("use " + TEST_TABLE_NAME + + "\nshow tables\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ something 0\n" + TEST_TABLE_NAME + + " 0\n$ ", outContent.toString()); + } + + @Test + public void useTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("use " + TEST_TABLE_NAME + + "\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("$ using " + TEST_TABLE_NAME + "\n$ ", outContent.toString()); + } + + @Test + public void incorrectCmdTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("bugaga\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("no such command, try again...\n", errContent.toString()); + } + + @Test + public void incorrectPutTest() { + ByteArrayInputStream in = new ByteArrayInputStream(("bugaga\nextremely_secret_word_for_test").getBytes()); + interpreter.scan = new Scanner(in); + interpreter.startUp(null, false); + assertEquals("no such command, try again...\n", errContent.toString()); + } + + @After + public void cleanUpStreams() { + System.setOut(null); + System.setErr(null); + testTableProvider.removeTable(TEST_TABLE_NAME); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectStoreableTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectStoreableTest.java new file mode 100644 index 000000000..1b0871b33 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectStoreableTest.java @@ -0,0 +1,111 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; + +public class ObjectStoreableTest { + private String name; + private List> columnTypes = new LinkedList>(); + private ObjectStoreable deserializedValue = new ObjectStoreable(); + public ObjectTable table; + private String valueToDeserialize; + private ObjectTable tempTable; + + @Before + public void initialization() throws IOException { + name = "TestTable"; + columnTypes.add(int.class); + columnTypes.add(long.class); + columnTypes.add(double.class); + columnTypes.add(float.class); + columnTypes.add(byte.class); + columnTypes.add(boolean.class); + columnTypes.add(String.class); + deserializedValue.subValueList.add(100500); + deserializedValue.subValueList.add((long) 10000000); + deserializedValue.subValueList.add(123.456); + deserializedValue.subValueList.add((float) 12.45); + deserializedValue.subValueList.add((byte) 100); + deserializedValue.subValueList.add(true); + deserializedValue.subValueList.add("\"ValueToTest\""); + deserializedValue.typeKeeper = columnTypes; + deserializedValue.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + tempTable = (ObjectTable) new ObjectTableProvider().createTable(name, columnTypes); + valueToDeserialize = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + } + + @Test + public void setColumnAtTest() { + ObjectStoreable tempStoreable = new ObjectStoreable(); + tempStoreable.subValueList.add(100500); + tempStoreable.subValueList.add((long) 10000000); + tempStoreable.subValueList.add(123.456); + tempStoreable.subValueList.add((float) 12.45); + tempStoreable.subValueList.add((byte) 100); + tempStoreable.subValueList.add(true); + tempStoreable.subValueList.add("\"ValueToTest\""); + tempStoreable.typeKeeper = columnTypes; + tempStoreable.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + assertEquals(tempStoreable, deserializedValue); + tempStoreable.subValueList.set(6, "\"AnotherValue\""); + tempStoreable.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"AnotherValue\"]"; + assertNotSame(tempStoreable, deserializedValue); + deserializedValue.setColumnAt(6, "\"AnotherValue\""); + assertEquals(tempStoreable, deserializedValue); + } + + @Test + public void getColumnAtTest() { + assertEquals((long) 10000000, deserializedValue.getColumnAt(1)); + } + + @Test + public void getIntAtTest() { + assertEquals((Integer) 100500, deserializedValue.getIntAt(0)); + } + + @Test + public void getLongAtTest() { + assertEquals((Long) Long.parseLong("10000000"), deserializedValue.getLongAt(1)); + } + + @Test + public void getByteAtTest() { + assertEquals((Byte) Byte.parseByte("100"), deserializedValue.getByteAt(4)); + } + + @Test + public void getFloatAtTest() { + assertEquals((Float) Float.parseFloat("12.45"), deserializedValue.getFloatAt(3)); + } + + @Test + public void getDoubleAtTest() { + assertEquals((Double) 123.456, deserializedValue.getDoubleAt(2)); + } + + @Test + public void getBooleanAtTest() { + assertEquals(true, deserializedValue.getBooleanAt(5)); + } + + @Test + public void getStringAtTest() { + assertEquals("\"ValueToTest\"", deserializedValue.getStringAt(6)); + } + + @After + public void cleanUp() { + new ObjectTableProvider().removeTable(name); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableProviderFactoryTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableProviderFactoryTest.java new file mode 100644 index 000000000..f1eadff0a --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableProviderFactoryTest.java @@ -0,0 +1,15 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.test; + +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProviderFactory; +import static org.junit.Assert.assertEquals; + +public class ObjectTableProviderFactoryTest { + @Test + public void createTest() { + ObjectTableProvider toCompare = new ObjectTableProvider("TestRoot"); + ObjectTableProvider qq = (ObjectTableProvider) new ObjectTableProviderFactory().create("TestRoot"); + assertEquals(toCompare, (ObjectTableProvider) new ObjectTableProviderFactory().create("TestRoot")); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableProviderTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableProviderTest.java new file mode 100644 index 000000000..94e2f1a51 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableProviderTest.java @@ -0,0 +1,90 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; +import java.io.IOException; +import java.text.ParseException; +import java.util.LinkedList; +import java.util.List; + +public class ObjectTableProviderTest extends ObjectTableProvider { + private String name; + private List> columnTypes = new LinkedList<>(); + private ObjectStoreable deserializedValue = new ObjectStoreable(); + private ObjectTable testTable; + @Before + public void initialization() throws IOException { + name = "TestTable"; + columnTypes.add(int.class); + columnTypes.add(long.class); + columnTypes.add(double.class); + columnTypes.add(float.class); + columnTypes.add(byte.class); + columnTypes.add(boolean.class); + columnTypes.add(String.class); + testTable = (ObjectTable) new ObjectTableProvider().createTable(name, columnTypes); + deserializedValue.subValueList.add(100500); + deserializedValue.subValueList.add((long) 10000000); + deserializedValue.subValueList.add(123.456); + deserializedValue.subValueList.add((float) 12.45); + deserializedValue.subValueList.add((byte) 100); + deserializedValue.subValueList.add(true); + deserializedValue.subValueList.add("\"ValueToTest\""); + deserializedValue.typeKeeper = columnTypes; + deserializedValue.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + } + + @Test + public void createAndGetTableTest() throws IOException { + name = "TestTable"; + assertEquals(null, createTable(name, columnTypes)); + assertEquals(testTable, getTable(name)); + } + + @Test + public void deserializeTest() throws IOException { + try { + assertEquals(deserializedValue, (ObjectStoreable) deserialize(testTable, + deserializedValue.serialisedValue)); + } catch (ParseException e) { + assertTrue(false); + } + } + + @Test + public void deserializeExceptionTest() throws IOException { + try { + assertEquals(deserializedValue, deserialize(testTable, + "we are waiting for exception here >:[")); + } catch (ParseException e) { + assertTrue(true); + } + } + + @Test + public void serializeTest() { + assertEquals(deserializedValue.serialisedValue, serialize(testTable, deserializedValue)); + } + + @Test + public void createForFirstTest() { + assertEquals(deserializedValue, createFor(testTable, deserializedValue.subValueList)); + } + + @Test + public void getTableNameTest() throws IOException { // Конечно же, стоит удостовериться, + // что в рабочей директории на момент тестирования нет таблиц. + assertEquals("TestTable", testTable.getName()); + } + + @After + public void cleanUp() { // Поясню. Теста на removeTable нет. Если бы метод не работал, то было бы + // сообщение "table_name exists". Его нет. + removeTable(name); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableTest.java new file mode 100644 index 000000000..864ff76d8 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Parallel/test/ObjectTableTest.java @@ -0,0 +1,137 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Parallel.test; + +import static junit.framework.Assert.assertNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.*; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.base.commands.Use; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Parallel.objects.ObjectTableProvider; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +public class ObjectTableTest { + private String name; + private List> columnTypes = new LinkedList>(); + private ObjectStoreable deserializedValue = new ObjectStoreable(); + private ObjectTable testTable; + + @Before + public void initialization() throws IOException { + name = "TestTable"; + columnTypes.add(int.class); + columnTypes.add(long.class); + testTable = (ObjectTable) new ObjectTableProvider().createTable(name, columnTypes); + deserializedValue.subValueList.add(100500); + deserializedValue.subValueList.add((long) 10000000); + deserializedValue.typeKeeper = columnTypes; + deserializedValue.serialisedValue = "[100500, 10000000]"; + } + + @Test + public void getNameTest() throws Exception { + assertEquals(name, testTable.getName()); + } + + @Test + public void putTest() throws Exception { + new Use().useFunction(name, null); + assertNull(testTable.put("Key", deserializedValue)); + assertEquals(deserializedValue, testTable.put("Key", deserializedValue)); + } + + @Test + public void getTest() throws Exception { + new Use().useFunction(name, null); + testTable.put("Key", deserializedValue); + assertEquals(deserializedValue, testTable.get("Key")); + } + + @Test + public void sizeTest() throws Exception { + new Use().useFunction(name, null); + for (Integer i = 0; i < 3; ++i) { + testTable.put(i.toString(), deserializedValue); + } + assertEquals(3, testTable.size()); + } + + @Test + public void listTest() throws Exception { + new Use().useFunction(name, null); + List toCompare = new LinkedList(); + for (Integer i = 0; i < 3; ++i) { + toCompare.add(i.toString()); + testTable.put(i.toString(), deserializedValue); + } + assertTrue(toCompare.containsAll(testTable.list())); + } + + @Test + public void removeTest() throws Exception { + new Use().useFunction(name, null); + testTable.put("Key", deserializedValue); + assertEquals(deserializedValue, testTable.remove("Key")); + } + + @Test + public void commitTest() { + for (Integer i = 0; i < 3; ++i) { + testTable.put(i.toString(), deserializedValue); + } + assertEquals(deserializedValue, testTable.get("0")); + assertEquals(deserializedValue, testTable.get("1")); + assertEquals(deserializedValue, testTable.get("2")); + assertEquals(3, testTable.commit()); + assertEquals(deserializedValue, testTable.get("0")); + assertEquals(deserializedValue, testTable.get("1")); + assertEquals(deserializedValue, testTable.get("2")); + } + + @Test + public void rollbackTest() { + for (Integer i = 0; i < 3; ++i) { + testTable.put(i.toString(), deserializedValue); + } + assertEquals(deserializedValue, testTable.get("0")); + assertEquals(deserializedValue, testTable.get("1")); + assertEquals(deserializedValue, testTable.get("2")); + assertEquals(3, testTable.rollback()); + assertNull(testTable.get("0")); + assertNull(testTable.get("1")); + assertNull(testTable.get("2")); + } + + @Test + public void getNumberOfUncommittedChangesTest() { + for (Integer i = 0; i < 2; ++i) { + String key = i.toString(); + testTable.put(key, deserializedValue); + } + assertEquals(2, testTable.getNumberOfUncommittedChanges()); + testTable.commit(); + assertEquals(0, testTable.getNumberOfUncommittedChanges()); + } + + @Test + public void getColumnsCountTest() { + assertEquals(2, testTable.getColumnsCount()); + } + + @Test + public void getColumnType() throws Exception { + new Use().useFunction(name, null); + assertEquals(int.class, testTable.getColumnType(0)); + assertEquals(long.class, testTable.getColumnType(1)); + } + + @After + public void cleanUp() { + new ObjectTableProvider().removeTable(name); + } +} + diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/CommandsTools.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/CommandsTools.java new file mode 100644 index 000000000..2724ad229 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/CommandsTools.java @@ -0,0 +1,17 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +public abstract class CommandsTools { + static final String JSON_REG_EX = "\\s*,\\s*(?=(?:(?:[^\"]*\"){2})*[^\"]*$)"; // Removes commas + // outside of "...". + static String usingTableName = new String(); + static ObjectTable currentTableObject; + static String dataBaseName = System.getProperty("fizteh.db.dir"); + static String signatureFileName = "signature.tsv"; + static Integer dirNum = 16; + static Integer fileNum = 16; + static String dirExt = ".dir"; + static String fileExt = ".dat"; + static int longestName = 260; + static Boolean tableIsChosen = false; +} + diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Exit.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Exit.java new file mode 100644 index 000000000..2e61bae4b --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Exit.java @@ -0,0 +1,24 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +public class Exit extends CommandsTools { + void exitFunction() throws Exception { + if (currentTableObject != null) { + new FillTable().fillTableFunction(currentTableObject); + } + System.exit(0); + } + boolean exitAndUseAvailable() { + if (currentTableObject != null) { + int uncommitedChanges = currentTableObject.storage.size() + - currentTableObject.commitStorage.size(); + if (uncommitedChanges == 0 || !tableIsChosen) { + return true; + } + System.out.println(uncommitedChanges + " uncommited changes"); + return false; + } + return true; + } +} + + diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/FillTable.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/FillTable.java new file mode 100644 index 000000000..1148c955d --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/FillTable.java @@ -0,0 +1,37 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; + +public class FillTable extends CommandsTools { + public void fillTableFunction(ObjectTable usingTable) throws Exception { + for (Map.Entry entry : usingTable.commitStorage.entrySet()) { + int hashCode = entry.getKey().hashCode(); + Integer nDirectory = hashCode % dirNum; + Integer nFile = hashCode / dirNum % fileNum; + Path fileName = Paths.get(dataBaseName + File.separator + usingTable.getName(), nDirectory + dirExt); + File file = new File(fileName.toString()); + if (!file.exists()) { + file.mkdir(); + } + fileName = Paths.get(fileName.toString(), nFile + fileExt); + file = new File(fileName.toString()); + if (!file.exists()) { + file.createNewFile(); + } + byte[] bytesKey = (" " + entry.getKey() + " ").getBytes(StandardCharsets.UTF_8); + DataOutputStream stream = new DataOutputStream(new FileOutputStream(fileName.toString(), true)); + stream.write((int) bytesKey.length); + stream.write(bytesKey); + byte[] bytesVal = ((" " + entry.getValue().serialisedValue + " ").getBytes(StandardCharsets.UTF_8)); + stream.write((int) bytesVal.length - 1); + stream.write(bytesVal); + stream.close(); + } + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Interpreter.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Interpreter.java new file mode 100644 index 000000000..33b264c37 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Interpreter.java @@ -0,0 +1,222 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import java.util.*; + +public class Interpreter extends CommandsTools { + private final String invitationalSymbol = "$ "; + + void parseDataFromCmdLine(String cmdLine) throws Exception { + String[] splittedLine = cmdLine.split("\\s*;\\s*"); + for (String line : splittedLine) { + String[] cmd = line.split("\\s+"); + executionFunction(cmd, true); // True means that data is from command line. + } + } + + void getCmdFromStream() throws Exception { + Scanner scan = new Scanner(System.in); + System.out.print(invitationalSymbol); + String[] cmd = scan.nextLine().split("\\s+"); + executionFunction(cmd, false); // False means that data is from "System.in". + } + + private void executionFunction(String[] cmd, boolean fromCmdLine) throws Exception { // The main interpreter + // function. + if (cmd[0].equals("create") && cmd.length > 2) { + String createParameter = new String(); // (...) - type list. + String tableName = cmd[1]; + for (int ind = 2; ind < cmd.length; ++ind) { + createParameter += cmd[ind] + " "; + } + createParameter = createParameter.substring(0, createParameter.length() - 1); + List> typeList = new LinkedList<>(); + try { + typeList = getTypeList(createParameter, fromCmdLine); + new ObjectTableProvider().createTable(tableName, typeList); + } catch (Exception e) { + System.err.println(e); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("use") && cmd.length == 2) { + String tableName = cmd[1]; + boolean changeUsingTable = false; + try { + if (tableIsChosen) { + new Use().useFunction(tableName, currentTableObject.getName()); + } else { + tableIsChosen = new Use().useFunction(tableName, null); + } + } catch (Exception e) { + printExceptionMessage(e); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("put") && cmd.length > 2) { + if (tableIsChosen) { + String putParameter = new String(); + String key = cmd[1]; + for (int ind = 2; ind < cmd.length; ++ind) { + putParameter += cmd[ind] + " "; + } + putParameter = putParameter.substring(0, putParameter.length() - 1); + try { + ObjectStoreable value = (ObjectStoreable) new ObjectTableProvider(). + deserialize(currentTableObject, putParameter); + currentTableObject.put(key, value); + } catch (Exception e) { + System.err.println(e); + } + } else { + informToChooseTable(); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("commit") && cmd.length == 1) { + currentTableObject.commit(); + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("show") && cmd[1].equals("tables") && cmd.length == 2) { + new ObjectTableProvider().getTableNames(); + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("get") && cmd.length == 2) { + try { + if (tableIsChosen) { + currentTableObject.get(cmd[1]); + } else { + informToChooseTable(); + } + } catch (Exception e) { + System.out.println(e); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("list") && cmd.length == 1) { + if (tableIsChosen) { + currentTableObject.list(); + } else { + informToChooseTable(); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("remove") && cmd.length == 2) { + if (tableIsChosen) { + try { + currentTableObject.remove(cmd[1]); + } catch (Exception e) { + System.err.println(e); + } + } else { + informToChooseTable(); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("drop") && cmd.length == 2) { + try { + new ObjectTableProvider().removeTable(cmd[1]); + } catch (Exception e) { + System.err.println(e); + } + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("rollback") && cmd.length == 1) { + currentTableObject.rollback(); + ifContinue(fromCmdLine); + } + + if (cmd[0].equals("exit") && cmd.length == 1) { + if (fromCmdLine) { + currentTableObject.commit(); + new Exit().exitFunction(); + } else { + if (new Exit().exitAndUseAvailable()) { + new Exit().exitFunction(); + } + } + ifContinue(fromCmdLine); + } + if (cmd.length != 0) { + syntaxError(); + } + ifContinue(fromCmdLine); + } + + void informToChooseTable() { + System.err.println("table is not chosen"); + } + + void ifContinue(boolean fromCmdLine) throws Exception { + if (fromCmdLine) { + return; + } else { + getCmdFromStream(); + } + } + + private void printExceptionMessage(Exception e) { + System.err.println(e); + } + + private List> getTypeList(String line, boolean fromCmdLine) throws Exception { + List> typeList = new LinkedList>(); + line = line.replaceAll("\\s*\\)\\s*", ""); + line = line.replaceAll("\\s*\\(\\s*", ""); + String[] tmp = line.split("\\s+"); + for (String str : tmp) { + Class type = getType(str); + if (type != null) { + typeList.add(type); + } else { + syntaxError(); + if (fromCmdLine) { + System.exit(1); + } else { + getCmdFromStream(); + } + } + } + return typeList; + } + + private Class getType(String str) { + if (str.equals("int")) { + return int.class; + } + if (str.equals("long")) { + return long.class; + } + if (str.equals("double")) { + return double.class; + } + if (str.equals("float")) { + return float.class; + } + if (str.equals("double")) { + return double.class; + } + if (str.equals("boolean")) { + return boolean.class; + } + if (str.equals("byte")) { + return byte.class; + } + if (str.equals("String")) { + return String.class; + } + return null; + } + + void syntaxError() { + System.err.println("incorrect syntax"); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Main.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Main.java new file mode 100644 index 000000000..1f8008088 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Main.java @@ -0,0 +1,18 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +public class Main { // Using JSON format. + public static void main(final String[] args) throws Exception { + new MakeDirs().makeDirsFunction(); + if (args.length == 0) { + new Interpreter().getCmdFromStream(); + } else { + String cmd = new String(); + for (String arg : args) { + cmd += arg + " "; + } + cmd = cmd.replaceAll("\\s+", " "); + new Interpreter().parseDataFromCmdLine(cmd.substring(0, cmd.length() - 1)); + new Exit().exitFunction(); + } + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/MakeDirs.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/MakeDirs.java new file mode 100644 index 000000000..f4ab90476 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/MakeDirs.java @@ -0,0 +1,24 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import java.io.File; + +public class MakeDirs extends CommandsTools { + void makeDirsFunction() throws Exception { + File file = new File(dataBaseName); + if (!file.exists()) { + file.mkdirs(); + } else { + if (!file.isDirectory()) { + System.err.println(dataBaseName + " is not a directory"); + System.exit(1); + } else { + for (File sub : file.listFiles()) { + if (!sub.isDirectory() && !sub.isHidden()) { + System.err.println(dataBaseName + File.separator + + sub.getName() + " is not a directory"); + } + } + } + } + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectStoreable.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectStoreable.java new file mode 100644 index 000000000..b6acb1f11 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectStoreable.java @@ -0,0 +1,232 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import java.text.ParseException; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +public class ObjectStoreable extends CommandsTools implements Storeable { + public List subValueList = new LinkedList<>(); + public String serialisedValue = new String(); + public List> typeKeeper = new LinkedList<>(); + public ObjectStoreable() {} + public ObjectStoreable(List values) { + int ind = 0; + serialisedValue = "["; + for (Object val : values) { + subValueList.add(val); + serialisedValue += val + ", "; + } + serialisedValue = serialisedValue.substring(0, serialisedValue.length() - 2); + serialisedValue += "]"; + } + public ObjectStoreable(Storeable value) { + subValueList = ((ObjectStoreable) value).subValueList; + serialisedValue = ((ObjectStoreable) value).serialisedValue; + typeKeeper = ((ObjectStoreable) value).typeKeeper; + } + public ObjectStoreable(ObjectTable table) { + typeKeeper = table.typeKeeper; + } + public ObjectStoreable(String value) throws ParseException { + ObjectStoreable obj = (ObjectStoreable) new ObjectTableProvider().deserialize(currentTableObject, value); + if (obj == null) { + return; + } + subValueList = obj.subValueList; + serialisedValue = obj.serialisedValue; + typeKeeper = obj.typeKeeper; + } + @Override + public int hashCode() { + return Objects.hashCode(this.serialisedValue); + } + @Override + public boolean equals(Object obj) { + ObjectStoreable storeableObj = (ObjectStoreable) obj; + if (this.serialisedValue.equals(storeableObj.serialisedValue) + && this.typeKeeper.equals(storeableObj.typeKeeper) + && this.subValueList.equals(storeableObj.subValueList)) { + return true; + } + return false; + } + @Override + public void setColumnAt(int columnIndex, Object value) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.subValueList.size()) { + throw new IndexOutOfBoundsException(); + } + List> toConvert = new LinkedList<>(); + toConvert.add(value.getClass()); + toConvert = convertToPrimitive(toConvert); + if (!typeKeeper.get(columnIndex).equals(toConvert.get(0))) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + return; + } catch (ColumnFormatException s) { + System.err.println(s); + return; + } + this.subValueList.set(columnIndex, value); + this.serialisedValue = ""; + serialisedValue = "["; + for (Object val : this.subValueList) { + serialisedValue += val + ", "; + } + serialisedValue = serialisedValue.substring(0, serialisedValue.length() - 2); // Откусить ", ". + serialisedValue += "]"; + return; + } + @Override + public Object getColumnAt(int columnIndex) throws IndexOutOfBoundsException { + if (subValueList.size() < columnIndex - 1) { + throw new IndexOutOfBoundsException(); + } + return subValueList.get(columnIndex); + } + @Override + public Integer getIntAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (columnIndex >= subValueList.size()) { + throw new IndexOutOfBoundsException(); + } + if (!this.typeKeeper.get(columnIndex).equals(int.class)) { + throw new ColumnFormatException(); + } + return (Integer) subValueList.get(columnIndex); + } + @Override + public Long getLongAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(long.class)) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + } catch (ColumnFormatException s) { + System.err.println(s); + } + return (Long) subValueList.get(columnIndex); + } + @Override + public Byte getByteAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(byte.class)) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + } catch (ColumnFormatException s) { + System.err.println(s); + } + return (Byte) subValueList.get(columnIndex); + } + @Override + public Float getFloatAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(float.class)) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + } catch (ColumnFormatException s) { + System.err.println(s); + } + return (Float) subValueList.get(columnIndex); + } + @Override + public Double getDoubleAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(double.class)) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + } catch (ColumnFormatException s) { + System.err.println(s); + } + return (Double) subValueList.get(columnIndex); + } + @Override + public Boolean getBooleanAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(boolean.class)) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + } catch (ColumnFormatException s) { + System.err.println(s); + } + return (Boolean) subValueList.get(columnIndex); + } + @Override + public String getStringAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + try { + if (columnIndex >= this.typeKeeper.size()) { + throw new IndexOutOfBoundsException(); + } + if (!typeKeeper.get(columnIndex).equals(String.class)) { + throw new ColumnFormatException(); + } + } catch (IndexOutOfBoundsException s) { + System.err.println(s); + } catch (ColumnFormatException s) { + System.err.println(s); + } + return subValueList.get(columnIndex).toString(); + } + private List> convertToPrimitive(List> list) { + List> toReturn = new LinkedList<>(); + for (Class object : list) { + if (object.equals(Integer.class)) { + toReturn.add(int.class); + continue; + } + if (object.equals(Long.class)) { + toReturn.add(long.class); + continue; + } + if (object.equals(Boolean.class)) { + toReturn.add(boolean.class); + continue; + } + if (object.equals(String.class)) { + toReturn.add(String.class); + continue; + } + if (object.equals(Byte.class)) { + toReturn.add(byte.class); + continue; + } + if (object.equals(Double.class)) { + toReturn.add(double.class); + continue; + } + if (object.equals(Float.class)) { + toReturn.add(float.class); + continue; + } + } + return toReturn; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTable.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTable.java new file mode 100644 index 000000000..68e57ba89 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTable.java @@ -0,0 +1,227 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +public class ObjectTable extends CommandsTools implements Table { + static int overwriteNum = 0; + public Stack lastChanges = new Stack(); + public Map storage = new HashMap<>(); + public Map commitStorage = new HashMap<>(); + public String tableName = new String(); + public List> typeKeeper = new LinkedList>(); + public ObjectTable() { + tableName = usingTableName; + typeKeeper = currentTableObject.typeKeeper; + } + public ObjectTable(Table table) { + ObjectTable temp = (ObjectTable) table; + this.tableName = temp.tableName; + this.typeKeeper = temp.typeKeeper; + } + public ObjectTable(String name) { + if (!new File(name).isAbsolute()) { + name = dataBaseName + File.separator + name; + } + this.tableName = new File(name).getName(); + String content = new String(); + try { + if (!new File(name + File.separator + signatureFileName).isAbsolute()) { + name = dataBaseName + File.separator + name; + } + content = readFile(name + File.separator + signatureFileName, Charset.defaultCharset()); + content.replaceAll("\\s+", " "); + String[] types = content.split(" "); + int ind = 0; + for (String type : types) { + typeKeeper.add(ind, getType(type)); + ++ind; + } + } catch (IOException s) { + System.err.println(s); + } + } + public ObjectTable(String name, List> typeList) { + int ind = 0; + for (Class type : typeList) { + typeKeeper.add(type); + } + tableName = name; + } + @Override + public int hashCode() { + return Objects.hashCode(this.tableName); + } + @Override + public boolean equals(Object obj) { + ObjectTable tableObj = (ObjectTable) obj; + if (this.tableName.equals(tableObj.tableName) && this.typeKeeper.equals(tableObj.typeKeeper)) { + return true; + } + return false; + } + @Override + public String getName() { + String nameToReturn = new File(tableName).getName(); + return nameToReturn; + } + @Override + public Storeable get(String key) throws IllegalArgumentException { // В документации в Index + // не сказано, когда кидать ParseException, однако согласно интерфейсу тут все-таки написано + // throws ParseException, но на самом деле это исключение тут не бросатется. + if (key == null) { + throw new IllegalArgumentException(); + } + ObjectStoreable value = storage.get(key); + if (value == null) { + System.err.println("not found"); + return null; + } + String serializedValue = value.serialisedValue; + System.out.println("found"); + System.out.println(serializedValue); + return value; + } + @Override + public Storeable put(String key, Storeable value) throws ColumnFormatException { + if (key == null || value == null) { + throw new IllegalArgumentException(); + } + if (!this.typeKeeper.equals(((ObjectStoreable) value).typeKeeper)) { + throw new ColumnFormatException(); + } + ObjectStoreable previousValue = storage.put(key, (ObjectStoreable) value); + if (previousValue == null) { + lastChanges.push(key); + lastChanges.push("remove"); + System.out.println("new"); + } else { + System.out.println("overwrite"); + lastChanges.push(previousValue); + lastChanges.push(key); + lastChanges.push("put"); + ++overwriteNum; + System.out.println(previousValue.serialisedValue); + } + return previousValue; + } + @Override + public Storeable remove(String key) { + if (key == null) { + throw new IllegalArgumentException(); + } + ObjectStoreable value = storage.remove(key); + commitStorage.remove(key); + if (value != null) { + lastChanges.push(value); + lastChanges.push(key); + lastChanges.push("put"); + System.out.println("removed"); + } else { + System.out.println("not found"); + } + return value; + } + @Override + public int size() { + return storage.size(); + } + @Override + public List list() { + LinkedList list = new LinkedList(); + int size = 0; + Set k = storage.keySet(); + for (Object iter : k) { + list.add(iter.toString()); + if (size < storage.size() - 1) { + System.out.print(iter + ", "); + } else { + System.out.print(iter); + } + ++size; + } + if (size != 0) { + System.out.println(); + } + return list; + } + @Override + public int commit() { + int savedKeys = Math.abs(storage.size() - commitStorage.size()); + Map tmp = new HashMap(commitStorage); + commitStorage = new HashMap(storage); + lastChanges.clear(); + return savedKeys; + } + @Override + public int rollback() throws IllegalArgumentException { + int changes = Math.abs(storage.size() - commitStorage.size() + overwriteNum); + while (!lastChanges.isEmpty()) { + Object tmpCmd = lastChanges.pop(); + if (tmpCmd.equals("put")) { + String key = lastChanges.pop().toString(); + ObjectStoreable value = (ObjectStoreable) lastChanges.pop(); + storage.put(key, value); + } + if (tmpCmd.equals("remove")) { + String key = lastChanges.pop().toString(); + storage.remove(key); + } + } + overwriteNum = 0; + return changes; + } + @Override + public int getNumberOfUncommittedChanges() { + int numberOfUncommitedChanges = Math.abs(storage.size() - commitStorage.size()); + return numberOfUncommitedChanges; + } + @Override + public int getColumnsCount() { + return typeKeeper.size(); + } + @Override + public Class getColumnType(int columnIndex) throws IndexOutOfBoundsException { + if (this.getColumnsCount() < columnIndex - 1) { + throw new IndexOutOfBoundsException(); + } + Class objectToReturn = typeKeeper.get(columnIndex); + return objectToReturn; + } + static String readFile(String path, Charset encoding) throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + String temp = new String(encoded, encoding); + return temp.replaceAll("^\\s*|\\s*$", ""); + } + private Class getType(String typeName) { + if (typeName.equals("int")) { + return int.class; + } + if (typeName.equals("long")) { + return long.class; + } + if (typeName.equals("byte")) { + return byte.class; + } + if (typeName.equals("float")) { + return float.class; + } + if (typeName.equals("double")) { + return double.class; + } + if (typeName.equals("boolean")) { + return boolean.class; + } + if (typeName.equals("String")) { + return String.class; + } + return null; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTableProvider.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTableProvider.java new file mode 100644 index 000000000..a143ec6dc --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTableProvider.java @@ -0,0 +1,313 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.storage.structured.TableProvider; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +public class ObjectTableProvider extends CommandsTools implements TableProvider { + private String rootDirectory = new String(); + public ObjectTableProvider() { + rootDirectory = dataBaseName; + } + public ObjectTableProvider(String dir) { + dataBaseName = dir; + rootDirectory = dir; + } + public int hashCode() { + return Objects.hashCode(this.rootDirectory); + } + @Override + public boolean equals(Object obj) { + ObjectTableProvider tempObj = (ObjectTableProvider) obj; + return tempObj.rootDirectory.equals(this.rootDirectory); + } + @Override + public Table getTable(String name) throws IllegalArgumentException { + checkException(name); + if (new File(rootDirectory + File.separator + name).exists()) { + return new ObjectTable(rootDirectory + File.separator + name); + } + return null; + } + @Override + public Table createTable(String name, List> columnTypes) throws IOException, IllegalArgumentException { + checkException(name); + File file = new File(rootDirectory + File.separator + name); + File signatureFile = new File(rootDirectory + File.separator + name + File.separator + signatureFileName); + if (file.exists()) { + System.out.println(name + " exists"); + } else { + file.mkdir(); + signatureFile.createNewFile(); + PrintWriter writer = new PrintWriter(signatureFile, "UTF-8"); + String tempTypes = new String(); + for (Class type : columnTypes) { + if (type.equals(String.class)) { + tempTypes += "String "; + } else { + tempTypes += type.getName() + " "; + } + } + tempTypes = tempTypes.substring(0, tempTypes.length() - 1); + writer.println(tempTypes); + writer.close(); + System.out.println("created"); + } + return new ObjectTable(name, columnTypes); + } + @Override + public void removeTable(String name) throws IllegalArgumentException, IllegalStateException { + if (name == null || name.length() > longestName) { + throw new IllegalArgumentException(); + } + String tableName = rootDirectory + File.separator + name; + File toBeRemoved = new File(tableName); + if (toBeRemoved.exists()) { + if (tableIsChosen) { + if (usingTableName.equals(name)) { + currentTableObject.storage.clear(); + currentTableObject.commitStorage.clear(); + tableIsChosen = false; + usingTableName = null; + } + } + recRem(tableName); + toBeRemoved.delete(); + System.out.println("dropped"); + } else { + throw new IllegalStateException(); + } + } + + @Override + public Storeable deserialize(Table table, String value) throws ParseException { + ObjectTable usingTable = (ObjectTable) table; + ObjectStoreable valueToReturn = new ObjectStoreable(); + String[] splittedValue = value.split(""); + if (!splittedValue[0].equals("[") || !splittedValue[splittedValue.length - 1].equals("]")) { + throw new ParseException(value, 0); + } + valueToReturn.serialisedValue = value; + value = value.replaceAll("^\\s*\\[\\s*|\\s*\\]\\s*$", ""); // Removing [ and ]. + String[] tempValue = value.split(JSON_REG_EX); // Split by comma. + if (usingTable.getColumnsCount() != tempValue.length) { + throw new ParseException(value, 0); + } + int index = 0; + List> typeList = new LinkedList<>(); + for (String str : tempValue) { + Object val = getValue(str, usingTable, usingTable.typeKeeper.get(index)); + if (val.equals("^incorrect$")) { + throw new ParseException(value, 0); + } + valueToReturn.subValueList.add(val); + typeList.add(val.getClass()); + ++index; + } + valueToReturn.typeKeeper = usingTable.typeKeeper; + return valueToReturn; + } + + @Override + public String serialize(Table table, Storeable value) throws ColumnFormatException { + ObjectStoreable valueToSerialize = (ObjectStoreable) value; + ObjectTable tableObj = (ObjectTable) table; + int index = 0; + for (Class type : tableObj.typeKeeper) { + if (!type.equals(valueToSerialize.typeKeeper.get(index))) { + throw new ColumnFormatException(); + } + ++index; + } + return valueToSerialize.serialisedValue; + } + + @Override + public Storeable createFor(Table table) { + return new ObjectStoreable((ObjectTable) table); + } + + @Override + public Storeable createFor(Table table, List values) throws ColumnFormatException, IndexOutOfBoundsException { + int ind = 0; + ObjectTable tempTable = new ObjectTable(table); + List> valTypes = new LinkedList>(); + valTypes = convertToPrimitive(values); + if (values.size() != tempTable.getColumnsCount()) { + throw new IndexOutOfBoundsException(); + } + if (!valTypes.equals(tempTable.typeKeeper)) { + throw new ColumnFormatException(); + } + ObjectStoreable toReturn = new ObjectStoreable(values); + toReturn.typeKeeper = tempTable.typeKeeper; + return toReturn; + } + + @Override + public List getTableNames() { + List list = new LinkedList(); + String currentFile = new String(); + int recordsAmount = 0; + File file = new File(rootDirectory); + for (File sub : file.listFiles()) { + if ((!sub.isHidden()) && sub.isDirectory()) { + recordsAmount = 0; + for (Integer i = 0; i < dirNum; ++i) { + currentFile = rootDirectory + File.separator + sub.getName() + File.separator + + i + dirExt; + File file1 = new File(currentFile); + if (file1.exists()) { + for (Integer j = 0; j < fileNum; ++j) { + currentFile = rootDirectory + File.separator + sub.getName() + File.separator + + i + dirExt + File.separator + j + fileExt; + file1 = new File(currentFile); + try { + if (file1.exists()) { + DataInputStream stream = new DataInputStream(new FileInputStream(currentFile)); + byte[] data = new byte[(int) file1.length()]; + stream.read(data); + String temp = new String(data, StandardCharsets.UTF_8); + recordsAmount += (temp.length() - temp.replaceAll(" ", "").length()) / 4; + } + } catch (FileNotFoundException e) { + return null; + } catch (IOException e) { + return null; + } + } + } + } + currentFile = new File(new File(new File(currentFile).getParent()).getParent()).getName(); + list.add(sub.getName()); + if (sub.getName().equals(usingTableName)) { + System.out.println(sub.getName() + " " + + (recordsAmount + currentTableObject.storage.size())); + } else { + System.out.println(sub.getName() + " " + recordsAmount); + } + } + } + return list; + } + + private Object getValue(String str, ObjectTable usingTable, Class expectedType) throws NumberFormatException { + for (Class type : usingTable.typeKeeper) { + if (expectedType.equals(int.class)) { + if (str.equals("null")) { + return null; + } + Integer toReturn = Integer.parseInt(str); + return toReturn; + } + if (expectedType.equals(long.class)) { + if (str.equals("null")) { + return null; + } + Long toReturn = Long.parseLong(str); + return toReturn; + } + if (expectedType.equals(boolean.class)) { + if (str.equals("null")) { + return null; + } + Boolean toReturn = Boolean.parseBoolean(str); + return toReturn; + } + if (expectedType.equals(String.class)) { + if (str.equals("null")) { + return null; + } + String[] tmp = str.split(""); + if (tmp[0].equals("\"") && tmp[tmp.length - 1].equals("\"")) { + return str; + } else { + throw new NumberFormatException(); + } + } + if (expectedType.equals(byte.class)) { + if (str.equals("null")) { + return null; + } + Byte toReturn = Byte.parseByte(str); + return toReturn; + } + if (expectedType.equals(double.class)) { + if (str.equals("null")) { + return null; + } + Double toReturn = Double.parseDouble(str); + return toReturn; + } + if (expectedType.equals(float.class)) { + if (str.equals("null")) { + return null; + } + Float toReturn = Float.parseFloat(str); + return toReturn; + } + } + return "^incorrect@"; + } + + void recRem(String myFile) { + File file = new File(myFile); + if (!file.exists()) { + return; + } + if (file.isDirectory()) { + for (File f : file.listFiles()) { + recRem(f.getAbsolutePath()); + } + } + file.delete(); + } + + public void checkException(String name) throws IllegalArgumentException { + if (name == null || name.length() > longestName) { + throw new IllegalArgumentException(); + } + } + + private List> convertToPrimitive(List list) { + List> toReturn = new LinkedList>(); + for (Object object : list) { + if (object.getClass().equals(Integer.class)) { + toReturn.add(int.class); + continue; + } + if (object.getClass().equals(Long.class)) { + toReturn.add(long.class); + continue; + } + if (object.getClass().equals(Boolean.class)) { + toReturn.add(boolean.class); + continue; + } + if (object.getClass().equals(String.class)) { + toReturn.add(String.class); + continue; + } + if (object.getClass().equals(Byte.class)) { + toReturn.add(byte.class); + continue; + } + if (object.getClass().equals(Double.class)) { + toReturn.add(double.class); + continue; + } + if (object.getClass().equals(Float.class)) { + toReturn.add(float.class); + continue; + } + } + return toReturn; + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTableProviderFactory.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTableProviderFactory.java new file mode 100644 index 000000000..c4adae9ab --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/ObjectTableProviderFactory.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; + +public class ObjectTableProviderFactory extends CommandsTools implements TableProviderFactory { + String dirName; + @Override + public TableProvider create(String dir) throws IllegalArgumentException { + dirName = dir; + try { + if (dir == null || dir.length() > longestName) { + throw new IllegalArgumentException(); + } + } catch (IllegalArgumentException s) { + System.err.println(s); + return null; + } + return new ObjectTableProvider(dir); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectStoreableTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectStoreableTest.java new file mode 100644 index 000000000..785ff4883 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectStoreableTest.java @@ -0,0 +1,109 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable.Test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectTableProvider; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; + +public class ObjectStoreableTest { + public String name; + public List> columnTypes = new LinkedList>(); + public ObjectTable tableToCompare = new ObjectTable(); + public ObjectStoreable deserializedValue = new ObjectStoreable(); + public ObjectTable table; + public String valueToDeserialize; + public ObjectTable tempTable; + @Before + public void initialization() throws IOException { + name = "TestTable"; + columnTypes.add(int.class); + columnTypes.add(long.class); + columnTypes.add(double.class); + columnTypes.add(float.class); + columnTypes.add(byte.class); + columnTypes.add(boolean.class); + columnTypes.add(String.class); + tableToCompare.typeKeeper = columnTypes; + tableToCompare.tableName = name; + deserializedValue.subValueList.add(100500); + deserializedValue.subValueList.add((long) 10000000); + deserializedValue.subValueList.add(123.456); + deserializedValue.subValueList.add((float) 12.45); + deserializedValue.subValueList.add((byte) 100); + deserializedValue.subValueList.add(true); + deserializedValue.subValueList.add("\"ValueToTest\""); + deserializedValue.typeKeeper = columnTypes; + deserializedValue.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + tempTable = (ObjectTable) new ObjectTableProvider().createTable(name, columnTypes); + valueToDeserialize = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + } + @Test + public void setColumnAtTest() { + ObjectStoreable tempStoreable = new ObjectStoreable(); + tempStoreable.subValueList.add(100500); + tempStoreable.subValueList.add((long) 10000000); + tempStoreable.subValueList.add(123.456); + tempStoreable.subValueList.add((float) 12.45); + tempStoreable.subValueList.add((byte) 100); + tempStoreable.subValueList.add(true); + tempStoreable.subValueList.add("\"ValueToTest\""); + tempStoreable.typeKeeper = columnTypes; + tempStoreable.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + assertEquals(tempStoreable, deserializedValue); + tempStoreable.subValueList.set(6, "\"AnotherValue\""); + tempStoreable.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"AnotherValue\"]"; + assertNotSame(tempStoreable, deserializedValue); + deserializedValue.setColumnAt(6, "\"AnotherValue\""); + assertEquals(tempStoreable, deserializedValue); + } + @Test + public void getColumnAtTest() { + assertEquals(100500, deserializedValue.getColumnAt(0)); + assertEquals((long) 10000000, deserializedValue.getColumnAt(1)); + assertEquals(123.456, deserializedValue.getColumnAt(2)); + assertEquals((float) 12.45, deserializedValue.getColumnAt(3)); + assertEquals((byte) 100, deserializedValue.getColumnAt(4)); + assertEquals(true, deserializedValue.getColumnAt(5)); + assertEquals("\"ValueToTest\"", deserializedValue.getColumnAt(6)); + } + @Test + public void getIntAtTest() { + assertEquals((Integer) 100500, deserializedValue.getIntAt(0)); + } + @Test + public void getLongAtTest() { + assertEquals((Long) Long.parseLong("10000000"), deserializedValue.getLongAt(1)); + } + @Test + public void getByteAtTest() { + assertEquals((Byte) Byte.parseByte("100"), deserializedValue.getByteAt(4)); + } + @Test + public void getFloatAtTest() { + assertEquals((Float) Float.parseFloat("12.45"), deserializedValue.getFloatAt(3)); + } + @Test + public void getDoubleAtTest() { + assertEquals((Double) 123.456, deserializedValue.getDoubleAt(2)); + } + @Test + public void getBooleanAtTest() { + assertEquals(true, deserializedValue.getBooleanAt(5)); + } + @Test + public void getStringAtTest() { + assertEquals("\"ValueToTest\"", deserializedValue.getStringAt(6)); + } + @After + public void cleanUp() { + new ObjectTableProvider().removeTable(name); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableProviderFactoryTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableProviderFactoryTest.java new file mode 100644 index 000000000..9e66e4600 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableProviderFactoryTest.java @@ -0,0 +1,15 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable.Test; + +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectTableProvider; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectTableProviderFactory; +import static org.junit.Assert.assertEquals; + +public class ObjectTableProviderFactoryTest { + @Test + public void createTest() { + ObjectTableProvider toCompare = new ObjectTableProvider("TestRoot"); + ObjectTableProvider qq = (ObjectTableProvider) new ObjectTableProviderFactory().create("TestRoot"); + assertEquals(toCompare, (ObjectTableProvider) new ObjectTableProviderFactory().create("TestRoot")); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableProviderTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableProviderTest.java new file mode 100644 index 000000000..3210197bf --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableProviderTest.java @@ -0,0 +1,94 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.*; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectStoreable; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectTable; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.ObjectTableProvider; +import java.io.IOException; +import java.text.ParseException; +import java.util.LinkedList; +import java.util.List; + +public class ObjectTableProviderTest extends ObjectTableProvider { + public String name; + public List> columnTypes = new LinkedList>(); + public ObjectTable tableToCompare = new ObjectTable(); + public ObjectStoreable deserializedValue = new ObjectStoreable(); + public ObjectTable table; + public String valueToDeserialize; + @Before + public void initialization() throws IOException { + name = "TestTable"; + columnTypes.add(int.class); + columnTypes.add(long.class); + columnTypes.add(double.class); + columnTypes.add(float.class); + columnTypes.add(byte.class); + columnTypes.add(boolean.class); + columnTypes.add(String.class); + tableToCompare.typeKeeper = columnTypes; + tableToCompare.tableName = name; + deserializedValue.subValueList.add(100500); + deserializedValue.subValueList.add((long) 10000000); + deserializedValue.subValueList.add(123.456); + deserializedValue.subValueList.add((float) 12.45); + deserializedValue.subValueList.add((byte) 100); + deserializedValue.subValueList.add(true); + deserializedValue.subValueList.add("\"ValueToTest\""); + deserializedValue.typeKeeper = columnTypes; + deserializedValue.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + table = (ObjectTable) createTable(name, columnTypes); + valueToDeserialize = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + } + @Test + public void createAndGetTableTest() throws IOException { + removeTable(name); + name = "TestTable"; + assertEquals(tableToCompare, createTable(name, columnTypes)); + assertEquals(tableToCompare, getTable(name)); + } + @Test + public void deserializeTest() throws ParseException, IOException { + assertEquals(deserializedValue, (ObjectStoreable) deserialize(table, valueToDeserialize)); + } + /*@Test(expected = IllegalArgumentException.class) // Это была попытка сделать тест на исключения. + //В следующей задаче я постараюсь это сделать. Просто нужно изменять кучу кода. + public void createNullTableTest() throws IOException { + createTable(null, columnTypes); + }*/ + @Test + public void serializeTest() { + assertEquals(valueToDeserialize, serialize(table, deserializedValue)); + } + @Test + public void createForTest() { + ObjectStoreable tempStoreable = new ObjectStoreable(); + tempStoreable.typeKeeper = table.typeKeeper; + assertEquals(tempStoreable, createFor(table)); + tempStoreable.subValueList = deserializedValue.subValueList; + tempStoreable.serialisedValue = deserializedValue.serialisedValue; + ObjectStoreable qq = (ObjectStoreable) createFor(table, deserializedValue.subValueList); + assertEquals(tempStoreable, (ObjectStoreable) createFor(table, deserializedValue.subValueList)); + } + @Test + public void getTableNamesTest() throws IOException { // Конечно же, стоит удостовериться, + // что в рабочей директории на момент тестирования нет таблиц. + List toCompare = new LinkedList(); + toCompare.add(name); + for (Integer ind = 0; ind < 1000; ++ind) { // Generating tables. + toCompare.add(ind.toString()); + createTable(ind.toString(), columnTypes); + } + assertTrue(toCompare.containsAll(getTableNames())); + for (Integer ind = 0; ind < 1000; ++ind) { + removeTable(ind.toString()); + } + } + @After + public void cleanUp() { // Поясню. Теста на removeTable нет. Если бы метод не работал, то было бы + // сообщение "table_name exists". Его нет. + removeTable(name); + } +} diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableTest.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableTest.java new file mode 100644 index 000000000..cc21f3381 --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Test/ObjectTableTest.java @@ -0,0 +1,131 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable.Test; + +import static junit.framework.Assert.assertNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.*; +import org.junit.Test; +import ru.fizteh.fivt.students.MaximGotovchits.Storeable.*; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +public class ObjectTableTest { + public String name; + public List> columnTypes = new LinkedList>(); + public ObjectTable tableToCompare = new ObjectTable(); + public ObjectStoreable deserializedValue = new ObjectStoreable(); + public ObjectTable table; + public String valueToDeserialize; + public ObjectTable tempTable; + @Before + public void initialization() throws IOException { + name = "TestTable"; + columnTypes.add(int.class); + columnTypes.add(long.class); + columnTypes.add(double.class); + columnTypes.add(float.class); + columnTypes.add(byte.class); + columnTypes.add(boolean.class); + columnTypes.add(String.class); + tableToCompare.typeKeeper = columnTypes; + tableToCompare.tableName = name; + deserializedValue.subValueList.add(100500); + deserializedValue.subValueList.add((long) 10000000); + deserializedValue.subValueList.add(123.456); + deserializedValue.subValueList.add((float) 12.45); + deserializedValue.subValueList.add((byte) 100); + deserializedValue.subValueList.add(true); + deserializedValue.subValueList.add("\"ValueToTest\""); + deserializedValue.typeKeeper = columnTypes; + deserializedValue.serialisedValue = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + tempTable = (ObjectTable) new ObjectTableProvider().createTable(name, columnTypes); + valueToDeserialize = "[100500, 10000000, 123.456, 12.45, 100, true, \"ValueToTest\"]"; + } + @Test + public void getNameTest() throws Exception { + new Use().useFunction(name, null); + assertEquals(name, new ObjectTable(name).getName()); + } + @Test + public void putTest() throws Exception { + new Use().useFunction(name, null); + assertNull(tempTable.put("Key", deserializedValue)); + assertEquals(deserializedValue, tempTable.put("Key", deserializedValue)); + } + @Test + public void getTest() throws Exception { + new Use().useFunction(name, null); + tempTable.put("Key", deserializedValue); + assertEquals(deserializedValue, tempTable.get("Key")); + } + @Test + public void sizeTest() throws Exception { + new Use().useFunction(name, null); + for (Integer i = 0; i < 1000; ++i) { + tempTable.put(i.toString(), deserializedValue); + } + assertEquals(1000, tempTable.size()); + } + @Test + public void listTest() throws Exception { + new Use().useFunction(name, null); + List toCompare = new LinkedList(); + for (Integer i = 0; i < 1000; ++i) { + toCompare.add(i.toString()); + tempTable.put(i.toString(), deserializedValue); + } + assertTrue(toCompare.containsAll(tempTable.list())); + } + @Test + public void removeTest() throws Exception { + new Use().useFunction(name, null); + tempTable.put("Key", deserializedValue); + assertEquals(deserializedValue, tempTable.remove("Key")); + } + @Test + public void commitTest() { + for (Integer i = 0; i < 1000; ++i) { + tempTable.put(i.toString(), deserializedValue); + } + assertEquals(1000, tempTable.commit()); + } + @Test + public void rollbackTest() { + for (Integer i = 0; i < 1000; ++i) { + tempTable.put(i.toString(), deserializedValue); + } + assertEquals(1000, tempTable.rollback()); + } + @Test + public void getNumberOfUncommittedChangesTest() { + for (Integer i = 0; i < 1000; ++i) { + String key = i.toString(); + tempTable.put(key, deserializedValue); + } + assertEquals(1000, tempTable.getNumberOfUncommittedChanges()); + tempTable.commit(); + assertEquals(0, tempTable.getNumberOfUncommittedChanges()); + } + @Test + public void getColumnsCountTest() { + assertEquals(7, tempTable.getColumnsCount()); + } + @Test + public void getColumnType() throws Exception { + new Use().useFunction(name, null); + assertEquals(int.class, tempTable.getColumnType(0)); + assertEquals(long.class, tempTable.getColumnType(1)); + assertEquals(double.class, tempTable.getColumnType(2)); + assertEquals(float.class, tempTable.getColumnType(3)); + assertEquals(byte.class, tempTable.getColumnType(4)); + assertEquals(boolean.class, tempTable.getColumnType(5)); + assertEquals(String.class, tempTable.getColumnType(6)); + } + @After + public void cleanUp() { + new ObjectTableProvider().removeTable(name); + } + +} + diff --git a/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Use.java b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Use.java new file mode 100644 index 000000000..4b5f87ddb --- /dev/null +++ b/src/ru/fizteh/fivt/students/MaximGotovchits/Storeable/Use.java @@ -0,0 +1,71 @@ +package ru.fizteh.fivt.students.MaximGotovchits.Storeable; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; + +public class Use extends CommandsTools { + public boolean useFunction(String tableName, String oldTableName) throws Exception { + if (!tableName.equals(oldTableName)) { + String outputName = tableName; + String tablePath = dataBaseName + "/" + tableName; + File file = new File(tablePath); + if (file.exists()) { + usingTableName = tableName; + if (tableIsChosen) { + new FillTable().fillTableFunction(currentTableObject); + currentTableObject.storage.clear(); + currentTableObject.commitStorage.clear(); + } + currentTableObject = new ObjectTable(dataBaseName + File.separator + usingTableName); + for (Integer i = 0; i < dirNum; ++i) { + for (Integer j = 0; j < fileNum; ++j) { + tablePath = dataBaseName + File.separator + tableName + File.separator + + i + dirExt + File.separator + j + fileExt; + if (new File(tablePath).exists()) { + fillStorage(tablePath, file); + PrintWriter writer = new PrintWriter(new File(tablePath)); + writer.print(""); + writer.close(); + } + } + } + System.out.println("using " + outputName); + tableIsChosen = true; + } else { + System.err.println(tableName + " not exists"); + return false; + } + } else { + System.out.println("using " + oldTableName); + } + usingTableName = currentTableObject.getName(); + return true; + } + void fillStorage(String datName, File file) throws IOException, ParseException { + DataInputStream stream = new DataInputStream(new FileInputStream(datName)); + file = new File(datName); + byte[] data = new byte[(int) file.length()]; + stream.read(data); + int counter = 0; + int offset = 0; + String keyForMap = ""; + String value = ""; + String aLL = new String(data); + while (counter < file.length()) { + offset = data[counter]; + keyForMap = new String(data, counter + 2, offset - 2, StandardCharsets.UTF_8); + counter = counter + offset + 1; + offset = data[counter]; + value = new String(data, counter + 2, data.length - counter - 3, StandardCharsets.UTF_8); + value = value.replaceAll("^\\s*|\\s*$", ""); + String tableName = new File(new File(datName).getParent()).getParent(); + ObjectStoreable valForMap = (ObjectStoreable) + new ObjectTableProvider().deserialize(new ObjectTable(tableName), value); + currentTableObject.storage.put(keyForMap, valForMap); + currentTableObject.commitStorage.put(keyForMap, valForMap); + counter = counter + offset + 3; + } + stream.close(); + } +}