diff --git a/src/ru/fizteh/fivt/storage/structured/ColumnFormatException.java b/src/ru/fizteh/fivt/storage/structured/ColumnFormatException.java new file mode 100644 index 000000000..7d6d19efa --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/ColumnFormatException.java @@ -0,0 +1,23 @@ +package ru.fizteh.fivt.storage.structured; + +/** + * Бросается при попытке извлечь из колонки {@link Storeable} значение не соответствующего типа, + * либо подставить в колонку значение несоответствующего типа. + */ +public class ColumnFormatException extends IllegalArgumentException { + + public ColumnFormatException() { + } + + public ColumnFormatException(String s) { + super(s); + } + + public ColumnFormatException(String message, Throwable cause) { + super(message, cause); + } + + public ColumnFormatException(Throwable cause) { + super(cause); + } +} diff --git a/src/ru/fizteh/fivt/storage/structured/Index.java b/src/ru/fizteh/fivt/storage/structured/Index.java new file mode 100644 index 000000000..3d37c40b4 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/Index.java @@ -0,0 +1,26 @@ +package ru.fizteh.fivt.storage.structured; + +/** + * Представляет базу для интерфейс для работы с таблицей, содержащей ключи-значения. + * Используется также для доступа к поисковому индексу. + */ +public interface Index { + /** + * Возвращает название таблицы или индекса. + * + * @return Название таблицы. + */ + String getName(); + + /** + * Получает значение по указанному ключу. + * + * @param key Ключ для поиска значения. Не может быть null. + * Для индексов по не-строковым полям аргумент представляет собой сериализованное значение колонки. + * Его потребуется распарсить. + * @return Значение. Если не найдено, возвращает null. + * + * @throws IllegalArgumentException Если значение параметра key является null. + */ + Storeable get(String key); +} diff --git a/src/ru/fizteh/fivt/storage/structured/IndexProvider.java b/src/ru/fizteh/fivt/storage/structured/IndexProvider.java new file mode 100644 index 000000000..f4ed79746 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/IndexProvider.java @@ -0,0 +1,30 @@ +package ru.fizteh.fivt.storage.structured; + +/** + * Дополнительный интерфейс к {@link ru.fizteh.fivt.storage.structured.TableProvider}, позволяющий создавать индексы на + * основе имеющейся таблицы. + */ +public interface IndexProvider extends TableProvider { + /** + * + * Возвращает индекс с таким именем, если он существует. + * + * @param name Имя индекса. Не должно быть null. + * @return Объект индекса + * @throws IllegalArgumentException Если имя индекса невалидно. + */ + Index getIndex(String name) throws IllegalArgumentException; + + /** + * Создает индекс. + * + * @param table Таблица, для которой нужно создать индекс. + * @param column Номер колонки. + * @param name Имя для будущего индекса. + * @return Свежесозданный индекс. null, если индекс уже был создан. + * @throws IllegalArgumentException Если таблица невалидна, указана неверная колонка или имя индекса, + * а также, если сущность с таким именем уже существует. + * @throws IllegalStateException Если индекс содержит невалидные элементы. + */ + Index createIndex(Table table, int column, String name) throws IllegalArgumentException, IllegalStateException; +} diff --git a/src/ru/fizteh/fivt/storage/structured/RemoteTableProvider.java b/src/ru/fizteh/fivt/storage/structured/RemoteTableProvider.java new file mode 100644 index 000000000..c3c5132d6 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/RemoteTableProvider.java @@ -0,0 +1,9 @@ +package ru.fizteh.fivt.storage.structured; + +import java.io.Closeable; + +/** + * Расширенный интерфейс {@link TableProvider}, с предоставлением метода {@link #close()}. + */ +public interface RemoteTableProvider extends TableProvider, Closeable { +} diff --git a/src/ru/fizteh/fivt/storage/structured/RemoteTableProviderFactory.java b/src/ru/fizteh/fivt/storage/structured/RemoteTableProviderFactory.java new file mode 100644 index 000000000..64cecacaa --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/RemoteTableProviderFactory.java @@ -0,0 +1,22 @@ +package ru.fizteh.fivt.storage.structured; + +import java.io.IOException; + +/** + * Представляет интерфейс для подключения к удаленному хранилищу. + * + * Предполагается, что реализация интерфейса клиента будет иметь публичный конструктор без параметров. + */ +public interface RemoteTableProviderFactory { + /** + * Возвращает {@link RemoteTableProvider} для работы с удаленных хранилищем. + * + * @param hostname Имя узла, на котором работает TCP-сервер хранилища. + * @param port Порт, на котором работает TCP-сервер хранилища. + * @return Remote-{@link RemoteTableProvider}, который подключен к TCP-серверу хранилища по заданному адресу. + * + * @throws IllegalArgumentException В случае некорректных входных параметров. + * @throws java.io.IOException В случае ошибок ввода/вывода. + */ + RemoteTableProvider connect(String hostname, int port) throws IOException; +} diff --git a/src/ru/fizteh/fivt/storage/structured/Storeable.java b/src/ru/fizteh/fivt/storage/structured/Storeable.java new file mode 100644 index 000000000..9b314acb7 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/Storeable.java @@ -0,0 +1,96 @@ +package ru.fizteh.fivt.storage.structured; + +/** + * Список фиксированной структуры, строка таблицы {@link Table}. + * + * Нумерация колонок с нуля. Позиция в списке соответствует колонке таблицы под тем же номером. + * + * С помощью {@link TableProvider} может быть сериализован или десериализован. + * + * Для получения объекта из нужной колонки воспользуйтесь соответствующим геттером. + * Для установки объекта а колонку воспользуйтесь {@link #setColumnAt(int, Object)} . + */ +public interface Storeable { + + /** + * Установить значение в колонку + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @param value - значение, которое нужно установить. + * Может быть null. + * Тип значения должен соответствовать декларированному типу колонки. + * @throws ColumnFormatException - Тип значения не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + void setColumnAt(int columnIndex, Object value) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, не приводя его к конкретному типу. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, без приведения типа. Может быть null. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Object getColumnAt(int columnIndex) throws IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к Integer. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к Integer. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Integer getIntAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к Long. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к Long. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Long getLongAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к Byte. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к Byte. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Byte getByteAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к Float. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к Float. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Float getFloatAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к Double. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к Double. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Double getDoubleAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к Boolean. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к Boolean. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + Boolean getBooleanAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает значение из данной колонки, приведя его к String. + * @param columnIndex - индекс колонки в таблице, начиная с нуля + * @return - значение в этой колонке, приведенное к String. Может быть null. + * @throws ColumnFormatException - Запрошенный тип не соответствует типу колонки. + * @throws IndexOutOfBoundsException - Неверный индекс колонки. + */ + String getStringAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException; +} diff --git a/src/ru/fizteh/fivt/storage/structured/Table.java b/src/ru/fizteh/fivt/storage/structured/Table.java new file mode 100644 index 000000000..111afe009 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/Table.java @@ -0,0 +1,92 @@ +package ru.fizteh.fivt.storage.structured; + +import java.io.IOException; +import java.util.List; + +/** + * Представляет интерфейс для работы с таблицей, содержащей ключи-значения. Ключи должны быть уникальными. + * + * Транзакционность: изменения фиксируются или откатываются с помощью методов {@link #commit()} или {@link #rollback()}, + * соответственно. Предполагается, что между вызовами этих методов никаких операций ввода-вывода не происходит. + * + * Данный интерфейс не является потокобезопасным. + */ +public interface Table extends Index { + + /** + * Устанавливает значение по указанному ключу. + * + * @param key Ключ для нового значения. Не может быть null. + * @param value Новое значение. Не может быть null. + * @return Значение, которое было записано по этому ключу ранее. Если ранее значения не было записано, + * возвращает null. + * + * @throws IllegalArgumentException Если значение параметров key или value является null. + * @throws ColumnFormatException - при попытке передать Storeable с колонками другого типа. + */ + Storeable put(String key, Storeable value) throws ColumnFormatException; + + /** + * Удаляет значение по указанному ключу. + * + * @param key Ключ для поиска значения. Не может быть null. + * @return Предыдущее значение. Если не найдено, возвращает null. + * + * @throws IllegalArgumentException Если значение параметра key является null. + */ + Storeable remove(String key); + + /** + * Возвращает количество ключей в таблице. Возвращает размер текущей версии, с учётом незафиксированных изменений. + * + * @return Количество ключей в таблице. + */ + int size(); + + /** + * Выводит список ключей таблицы, с учётом незафиксированных изменений. + * + * @return Список ключей. + */ + List list(); + + /** + * Выполняет фиксацию изменений. + * + * @return Число записанных изменений. + * + * @throws java.io.IOException если произошла ошибка ввода/вывода. Целостность таблицы не гарантируется. + */ + int commit() throws IOException; + + /** + * Выполняет откат изменений с момента последней фиксации. + * + * @return Число откаченных изменений. + */ + int rollback(); + + /** + * Возвращает количество изменений, ожидающих фиксации. + * + * @return Количество изменений, ожидающих фиксации. + */ + int getNumberOfUncommittedChanges(); + + /** + * Возвращает количество колонок в таблице. + * + * @return Количество колонок в таблице. + */ + int getColumnsCount(); + + /** + * Возвращает тип значений в колонке. + * + * @param columnIndex Индекс колонки. Начинается с нуля. + * @return Класс, представляющий тип значения. + * + * @throws IndexOutOfBoundsException - неверный индекс колонки + */ + Class getColumnType(int columnIndex) throws IndexOutOfBoundsException; +} diff --git a/src/ru/fizteh/fivt/storage/structured/TableProvider.java b/src/ru/fizteh/fivt/storage/structured/TableProvider.java new file mode 100644 index 000000000..dec271bb7 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/TableProvider.java @@ -0,0 +1,106 @@ +package ru.fizteh.fivt.storage.structured; + +import java.io.IOException; +import java.text.ParseException; +import java.util.List; + +/** + * Управляющий класс для работы с {@link Table таблицами} + * + * Предполагает, что актуальная версия с устройства хранения, сохраняется при создании + * экземпляра объекта. Далее ввод-вывод выполняется только в момент создания и удаления + * таблиц. + * + * Данный интерфейс не является потокобезопасным. + */ +public interface TableProvider { + + /** + * Возвращает таблицу с указанным названием. + * + * Последовательные вызовы метода с одинаковыми аргументами должны возвращать один и тот же объект таблицы, + * если он не был удален с помощью {@link #removeTable(String)}. + * + * @param name Название таблицы. + * @return Объект, представляющий таблицу. Если таблицы с указанным именем не существует, возвращает null. + * + * @throws IllegalArgumentException Если название таблицы null или имеет недопустимое значение. + */ + Table getTable(String name); + + /** + * Создаёт таблицу с указанным названием. + * Создает новую таблицу. Совершает необходимые дисковые операции. + * + * @param name Название таблицы. + * @param columnTypes Типы колонок таблицы. Не может быть пустой. + * @return Объект, представляющий таблицу. Если таблица с указанным именем существует, возвращает null. + * + * @throws IllegalArgumentException Если название таблицы null или имеет недопустимое значение. Если список типов + * колонок null или содержит недопустимые значения. + * @throws java.io.IOException При ошибках ввода/вывода. + */ + Table createTable(String name, List> columnTypes) throws IOException; + + /** + * Удаляет существующую таблицу с указанным названием. + * + * Объект удаленной таблицы, если был кем-то взят с помощью {@link #getTable(String)}, + * с этого момента должен бросать {@link IllegalStateException}. + * + * @param name Название таблицы. + * + * @throws IllegalArgumentException Если название таблицы null или имеет недопустимое значение. + * @throws IllegalStateException Если таблицы с указанным названием не существует. + * @throws java.io.IOException - при ошибках ввода/вывода. + */ + void removeTable(String name) throws IOException; + + /** + * Преобразовывает строку в объект {@link Storeable}, соответствующий структуре таблицы. + * + * @param table Таблица, которой должен принадлежать {@link Storeable}. + * @param value Строка, из которой нужно прочитать {@link Storeable}. + * @return Прочитанный {@link Storeable}. + * + * @throws ParseException - при каких-либо несоответстиях в прочитанных данных. + */ + Storeable deserialize(Table table, String value) throws ParseException; + + /** + * Преобразовывает объект {@link Storeable} в строку. + * + * @param table Таблица, которой должен принадлежать {@link Storeable}. + * @param value {@link Storeable}, который нужно записать. + * @return Строка с записанным значением. + * + * @throws ColumnFormatException При несоответствии типа в {@link Storeable} и типа колонки в таблице. + */ + String serialize(Table table, Storeable value) throws ColumnFormatException; + + /** + * Создает новый пустой {@link Storeable} для указанной таблицы. + * + * @param table Таблица, которой должен принадлежать {@link Storeable}. + * @return Пустой {@link Storeable}, нацеленный на использование с этой таблицей. + */ + Storeable createFor(Table table); + + /** + * Создает новый {@link Storeable} для указанной таблицы, подставляя туда переданные значения. + * + * @param table Таблица, которой должен принадлежать {@link Storeable}. + * @param values Список значений, которыми нужно проинициализировать поля Storeable. + * @return {@link Storeable}, проинициализированный переданными значениями. + * @throws ColumnFormatException При несоответствии типа переданного значения и колонки. + * @throws IndexOutOfBoundsException При несоответствии числа переданных значений и числа колонок. + */ + Storeable createFor(Table table, List values) throws ColumnFormatException, IndexOutOfBoundsException; + + /** + * Возвращает имена существующих таблиц, которые могут быть получены с помощью {@link #getTable(String)}. + * + * @return Имена существующих таблиц. + */ + List getTableNames(); +} diff --git a/src/ru/fizteh/fivt/storage/structured/TableProviderFactory.java b/src/ru/fizteh/fivt/storage/structured/TableProviderFactory.java new file mode 100644 index 000000000..2f71d0dc1 --- /dev/null +++ b/src/ru/fizteh/fivt/storage/structured/TableProviderFactory.java @@ -0,0 +1,22 @@ +package ru.fizteh.fivt.storage.structured; + +import java.io.IOException; + +/** + * Представляет интерфейс для создание экземпляров {@link TableProvider}. + * + * Предполагается, что реализация интерфейса фабрики будет иметь публичный конструктор без параметров. + */ +public interface TableProviderFactory { + + /** + * Возвращает объект для работы с базой данных. + * + * @param path Директория с файлами базы данных. + * @return Объект для работы с базой данных, который будет работать в указанной директории. + * + * @throws IllegalArgumentException Если значение директории null или имеет недопустимое значение. + * @throws java.io.IOException В случае ошибок ввода/вывода. + */ + TableProvider create(String path) throws IOException; +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/BadFileException.java b/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/BadFileException.java deleted file mode 100644 index ea47a8256..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/BadFileException.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; - -import java.io.IOException; - -public class BadFileException extends IOException { -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/CommandFileMap.java b/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/CommandFileMap.java deleted file mode 100644 index 3b381c6c9..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/CommandFileMap.java +++ /dev/null @@ -1,4 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; - -public abstract class CommandFileMap extends Command { -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandGet.java b/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandGet.java deleted file mode 100644 index eaf3b41bc..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandGet.java +++ /dev/null @@ -1,19 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; - -public class FmCommandGet extends CommandFileMap { - public FmCommandGet() { - name = "get"; - numberOfArguments = 2; - } - - @Override - public boolean run(FileMap myFileMap, String[] args) { - String value = myFileMap.get(args[1]); - if (value != null) { - System.out.println("found\n" + value); - } else { - System.out.println("not found"); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandList.java b/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandList.java deleted file mode 100644 index b0257ddc1..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandList.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; - -import java.util.List; - -public class FmCommandList extends CommandFileMap { - public FmCommandList() { - name = "list"; - numberOfArguments = 1; - } - - @Override - public boolean run(FileMap myFileMap, String[] args) { - List allKeys = myFileMap.list(); - int counter = 0; - for (String oneKey : allKeys) { - if (counter > 0) { - System.out.print(", "); - } - System.out.print(oneKey); - ++counter; - } - if (counter > 0) { - System.out.println(); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandPut.java b/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandPut.java deleted file mode 100644 index a7c40224b..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandPut.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; - -public class FmCommandPut extends CommandFileMap { - public FmCommandPut() { - name = "put"; - numberOfArguments = 3; - } - @Override - public boolean run(FileMap myFileMap, String[] args) { - String oldValue = myFileMap.put(args[1], args[2]); - if (oldValue != null) { - System.out.println("overwrite\n" + oldValue); - } else { - System.out.println("new"); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandRemove.java b/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandRemove.java deleted file mode 100644 index 38c5b416a..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FmCommandRemove.java +++ /dev/null @@ -1,19 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; - -public class FmCommandRemove extends CommandFileMap { - public FmCommandRemove() { - name = "remove"; - numberOfArguments = 2; - } - @Override - public boolean run(FileMap myFileMap, String[] args) { - String value = myFileMap.remove(args[1]); - if (value != null) { - System.out.println("removed"); - } else { - System.out.println("not found"); - } - return true; - } -} - diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandCommit.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandCommit.java deleted file mode 100644 index 6aa0d08da..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandCommit.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; - -public class CommandCommit extends CommandMultiFileHashMap{ - public CommandCommit() { - name = "commit"; - numberOfArguments = 1; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (currentTable == null) { - System.out.println("no table"); - } else { - System.out.println(currentTable.commit()); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandCreate.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandCreate.java deleted file mode 100644 index 39320730b..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandCreate.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.Path; - -public class CommandCreate extends CommandMultiFileHashMap { - public CommandCreate() { - name = "create"; - numberOfArguments = 2; - } - - @Override - public boolean run(MFileHashMap myMultiDataBase, String[] args) { - Path pathOfNewTable = Paths.get(myMultiDataBase.getDataBaseDirectory() - + System.getProperty("file.separator") + args[1]); - if (Files.exists(pathOfNewTable) & Files.isDirectory(pathOfNewTable)) { - System.out.println(args[1] + " exists"); - return true; - } - try { - Files.createDirectory(pathOfNewTable); - System.out.println("created"); - myMultiDataBase.addTable(args[1], new FileMap(pathOfNewTable.toString())); - } catch (IOException e) { - System.out.println(name + ": error while creating directory"); - return false; - } - return true; - } -} - diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandDrop.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandDrop.java deleted file mode 100644 index f88b54081..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandDrop.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.ShellPackage.CommandRm; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class CommandDrop extends CommandMultiFileHashMap { - public CommandDrop() { - name = "drop"; - numberOfArguments = 2; - } - - @Override - public boolean run(MFileHashMap myDataBase, String[] args) { - CommandRm myRemover = new CommandRm(); - Path pathForRemoveTable = Paths.get(myDataBase.getDataBaseDirectory(), args[1]); - if (!Files.exists(pathForRemoveTable)) { - System.out.println(args[1] + " not exists"); - return true; - } - String[] argsArray = { - "rm", - "-r", - pathForRemoveTable.toString() - }; - if (myRemover.run(argsArray)) { - System.out.println("dropped"); - myDataBase.dropTable(args[1]); - return true; - } else { - System.err.println(name + " : error while removing table's directory"); - return false; - } - } -} - diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandGetDistribute.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandGetDistribute.java deleted file mode 100644 index 717ce78a2..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandGetDistribute.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FmCommandGet; - -public class CommandGetDistribute extends CommandMultiFileHashMap { - public CommandGetDistribute() { - name = "get"; - numberOfArguments = 2; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (myMap.getCurrentTable() == null) { - System.out.println("no table"); - return true; - } - FmCommandGet commandGet = new FmCommandGet(); - return commandGet.run(currentTable, args); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandListDistribute.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandListDistribute.java deleted file mode 100644 index 3c35d4906..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandListDistribute.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FmCommandList; - -public class CommandListDistribute extends CommandMultiFileHashMap { - public CommandListDistribute() { - name = "list"; - numberOfArguments = 1; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (myMap.getCurrentTable() == null) { - System.out.println("no table"); - return true; - } - FmCommandList commandList = new FmCommandList(); - return commandList.run(currentTable, args); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandMultiFileHashMap.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandMultiFileHashMap.java deleted file mode 100644 index ccaffe6b4..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandMultiFileHashMap.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.Command; - -public abstract class CommandMultiFileHashMap extends Command { -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandPutDistribute.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandPutDistribute.java deleted file mode 100644 index 7b238c408..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandPutDistribute.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FmCommandPut; - -public class CommandPutDistribute extends CommandMultiFileHashMap { - public CommandPutDistribute() { - name = "put"; - numberOfArguments = 3; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (myMap.getCurrentTable() == null) { - System.out.println("no table"); - return true; - } - FmCommandPut commandPut = new FmCommandPut(); - return commandPut.run(currentTable, args); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandRemoveDistribute.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandRemoveDistribute.java deleted file mode 100644 index afcbef859..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandRemoveDistribute.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FmCommandRemove; - -public class CommandRemoveDistribute extends CommandMultiFileHashMap { - public CommandRemoveDistribute() { - name = "remove"; - numberOfArguments = 2; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (myMap.getCurrentTable() == null) { - System.out.println("no table"); - return true; - } - FmCommandRemove removeCommand = new FmCommandRemove(); - return removeCommand.run(currentTable, args); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandRollback.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandRollback.java deleted file mode 100644 index 67c5f09db..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandRollback.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; - -public class CommandRollback extends CommandMultiFileHashMap { - public CommandRollback() { - name = "rollback"; - numberOfArguments = 1; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (currentTable == null) { - System.out.println("no table"); - } else { - System.out.println(currentTable.rollback()); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandShowTables.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandShowTables.java deleted file mode 100644 index 0b3dac58e..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandShowTables.java +++ /dev/null @@ -1,19 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -public class CommandShowTables extends CommandMultiFileHashMap { - public CommandShowTables() { - name = "show"; - numberOfArguments = 2; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - if (!args[1].equals("tables")) { - System.out.println(name + ": wrong arguments"); - return false; - } - System.out.println("table_name row_count"); - myMap.showTables(); - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandSize.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandSize.java deleted file mode 100644 index b5574c93b..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandSize.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; - -public class CommandSize extends CommandMultiFileHashMap { - public CommandSize() { - name = "size"; - numberOfArguments = 1; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap currentTable = myMap.getCurrentTable(); - if (currentTable == null) { - System.out.println("no table"); - } else { - System.out.println(currentTable.size()); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandUse.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandUse.java deleted file mode 100644 index 42d76559d..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/CommandUse.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; - -public class CommandUse extends CommandMultiFileHashMap { - public CommandUse() { - name = "use"; - numberOfArguments = 2; - } - - @Override - public boolean run(MFileHashMap myMap, String[] args) { - FileMap newCurrentTable = myMap.findTableByName(args[1]); - if (newCurrentTable != null) { - FileMap currentTable = myMap.getCurrentTable(); - if (currentTable == null) { - myMap.setCurrentTable(newCurrentTable); - System.out.println("using " + args[1]); - } else if (currentTable.getNumberOfUncommitedChanges() > 0) { - System.out.println(currentTable.getNumberOfUncommitedChanges() + " unsaved changes"); - } else { - myMap.setCurrentTable(newCurrentTable); - System.out.println("using " + args[1]); - } - } else { - System.out.println(args[1] + " not exists"); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/MFileHashMap.java b/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/MFileHashMap.java deleted file mode 100644 index 59cdcbce8..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/MFileHashMap.java +++ /dev/null @@ -1,126 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Set; -import java.util.Map.Entry; - -import ru.fizteh.fivt.storage.strings.Table; -import ru.fizteh.fivt.storage.strings.TableProvider; -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.FileMap; -import ru.fizteh.fivt.students.titov.JUnit.ShellPackage.FileUtils; - -public class MFileHashMap implements TableProvider { - private String dataBaseDirectory; - private HashMap tables; - private FileMap currentTable; - - public MFileHashMap(String newDirectory) { - dataBaseDirectory = newDirectory; - tables = new HashMap<>(); - init(); - } - - public Table getTable(String name) throws IllegalArgumentException { - if (name == null) { - throw new IllegalArgumentException(); - } - if (tables.containsKey(name)) { - return tables.get(name); - } else { - return null; - } - } - - public Table createTable(String name) throws IllegalArgumentException { - if (name == null) { - throw new IllegalArgumentException(); - } - if (tables.containsKey(name)) { - return null; - } else { - Path pathOfNewTable = Paths.get(dataBaseDirectory, name); - try { - Files.createDirectory(pathOfNewTable); - FileMap newTable = new FileMap(pathOfNewTable.toString()); - tables.put(name, newTable); - return newTable; - } catch (IOException e) { - throw new IllegalArgumentException(); - } - } - } - - public void removeTable(String name) throws IllegalArgumentException, IllegalStateException { - if (name == null) { - throw new IllegalArgumentException(); - } - if (tables.containsKey(name)) { - Path pathForRemoveTable = Paths.get(dataBaseDirectory, name); - tables.remove(name); - if (!FileUtils.rmdir(pathForRemoveTable)) { - throw new IllegalArgumentException(); - } - } else { - throw new IllegalStateException(); - } - } - - - public void addTable(String tableName, FileMap newFileMap) { - tables.put(tableName, newFileMap); - } - - public void dropTable(String tableName) { - if (tables.get(tableName).equals(currentTable)) { - currentTable = null; - } - tables.remove(tableName); - } - - public String getDataBaseDirectory() { - return dataBaseDirectory; - } - - public void showTables() { - Set> pairSet = tables.entrySet(); - for (Entry oneTable: pairSet) { - System.out.println(oneTable.getKey() + " " - + oneTable.getValue().size()); - } - } - - public void setCurrentTable(FileMap newCurrentTable) { - currentTable = newCurrentTable; - } - - public FileMap getCurrentTable() { - return currentTable; - } - - public boolean init() { - String[] listOfFiles = new File(dataBaseDirectory).list(); - for (String oneFile: listOfFiles) { - Path oneTablePath = Paths.get(dataBaseDirectory, oneFile); - if (Files.isDirectory(oneTablePath)) { - tables.put(oneFile, new FileMap(oneTablePath.toString())); - } - } - boolean allRight = true; - Set> pairSet = tables.entrySet(); - for (Entry oneFileMap: pairSet) { - if (!oneFileMap.getValue().init()) { - allRight = false; - } - } - return allRight; - } - - public FileMap findTableByName(String requiredFileMapName) { - return tables.get(requiredFileMapName); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCd.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCd.java deleted file mode 100644 index 2173d8fd3..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCd.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.nio.file.Files; -import java.nio.file.Path; - -public class CommandCd extends Command { - public CommandCd() { - name = "cd"; - numberOfArguments = 2; - } - - @Override - public boolean run(final String[] arguments) { - if (arguments.length == 1) { - System.setProperty("user.dir", "/"); - return true; - } - if (arguments.length != numberOfArguments) { - System.out.println("wrong number of arguments"); - return false; - } - Path newWorkDirectory = PathsFunction.toAbsolutePathString(arguments[1]); - if (Files.isDirectory(newWorkDirectory)) { - System.setProperty("user.dir", newWorkDirectory.toString()); - return true; - } else { - if (Files.exists(newWorkDirectory)) { - System.out.println(name + ": \'" + arguments[1] - + "\': Not a directory"); - } else { - System.out.println(name + ": \'" + arguments[1] - + "\': No such file or directory"); - } - return false; - } - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCp.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCp.java deleted file mode 100644 index 55e767252..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCp.java +++ /dev/null @@ -1,105 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; - -public class CommandCp extends Command { - public CommandCp() { - name = "cp"; - numberOfArguments = 4; - } - - @Override - public boolean run(final String[] arguments) { - if (arguments.length != numberOfArguments - & arguments.length != numberOfArguments - 1) { - System.out.println("wrong number of arguments"); - return false; - } - boolean recursive = - (arguments.length == numberOfArguments & arguments[1].equals("-r")); - if (!recursive) { - return generalCopy(arguments); - } else { - return recursiveCopy(arguments); - } - } - - private boolean generalCopy(final String[] arguments) { - if (numberOfArguments - 1 != arguments.length) { - System.out.println("wrong number of arguments"); - return false; - } - Path startPath = PathsFunction.toAbsolutePathString(arguments[1]); - Path destinationPath = PathsFunction.toAbsolutePathString(arguments[2]); - Path fileName = Paths.get(arguments[1]).getFileName(); - - if (startPath.equals(destinationPath)) { - System.out.println(name + ": \'" + arguments[1] + "\' and \'" - + arguments[2] + "\' are the same file or directory"); - return false; - } - if (Files.isDirectory(startPath)) { - System.out.println(name + ": " + arguments[1] - + " is a directory (not copied)."); - return false; - } - - if (!Files.exists(startPath)) { - System.out.println(name + ": cannot copy \'" + arguments[1] + "\'" - + ": No such file or directory"); - return false; - } - - if (Files.isDirectory(destinationPath)) { - destinationPath = destinationPath.resolve(fileName); - } else if (destinationPath.toString().endsWith("/")) { - System.out.println(name + ": cannot copy \'" + fileName + "\' to \'" - + arguments[2] + "\': Not a directory"); - return false; - } - - try { - Files.copy(startPath, destinationPath, StandardCopyOption.REPLACE_EXISTING); - } catch (Exception e) { - System.out.println(name + "; cannot create regular file \'" + arguments[2] - + "\'" + ": Not a directory"); - return false; - } - return true; - } - - private boolean recursiveCopy(final String[] arguments) { - Path startPath = PathsFunction.toAbsolutePathString(arguments[2]); - - Path destinationPath = PathsFunction.toAbsolutePathString(arguments[3]); - - - if (!Files.isDirectory(destinationPath) & Files.exists(destinationPath)) { - System.out.println("\'" + arguments[3] + "\' isn't a directory"); - return false; - } - if (startPath.equals(destinationPath)) { - System.out.println(name + ": \'" + arguments[2] + "\' and \'" - + arguments[3] + "\' are the same file or directory"); - return false; - } - - if (Files.exists(destinationPath)) { - destinationPath = - destinationPath.resolve(startPath.getFileName()).normalize(); - } - - FileVisitorCopy myFileVisitorCopy = - new FileVisitorCopy(startPath, destinationPath); - try { - Files.walkFileTree(startPath, myFileVisitorCopy); - } catch (IOException e) { - return false; - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandLs.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandLs.java deleted file mode 100644 index 0c70b688c..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandLs.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.io.File; - -public class CommandLs extends Command { - public CommandLs() { - name = "ls"; - numberOfArguments = 1; - } - - @Override - public boolean run(final String[] arguments) { - if (arguments.length != numberOfArguments) { - System.out.println("wrong number of arguments"); - return false; - } - String[] listOfFiles = new File(System.getProperty("user.dir")).list(); - for (String oneFileName : listOfFiles) { - System.out.println(oneFileName); - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandMv.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandMv.java deleted file mode 100644 index 4fec811fe..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandMv.java +++ /dev/null @@ -1,43 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.nio.file.Files; -import java.nio.file.Path; - -public class CommandMv extends Command { - public CommandMv() { - name = "mv"; - numberOfArguments = 3; - } - - @Override - public boolean run(final String[] arguments) { - if (arguments.length != numberOfArguments) { - System.out.println("wrong number of arguments"); - return false; - } - Path startPath = PathsFunction.toAbsolutePathString(arguments[1]); - Path destinationPath = PathsFunction.toAbsolutePathString(arguments[2]); - Path fileName = startPath.getFileName(); - - if (!Files.exists(startPath)) { - System.out.println(name + ": cannot stat \'" + arguments[1] - + "\': No such file or directory"); - return false; - } - - if (Files.isDirectory(destinationPath)) { - destinationPath = destinationPath.resolve(fileName); - } else if (destinationPath.toString().endsWith("/")) { - System.out.println(name + ": cannot move \'" + arguments[1] + "\' to \'" - + arguments[2] + "\': Not a directory"); - return false; - } - - try { - Files.move(startPath, destinationPath); - } catch (Exception e) { - return false; - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandPwd.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandPwd.java deleted file mode 100644 index 1559115df..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandPwd.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -public class CommandPwd extends Command { - public CommandPwd() { - name = "pwd"; - numberOfArguments = 1; - } - - @Override - public boolean run(final String[] args) { - if (args.length != numberOfArguments) { - System.out.println("wrong number of arguments"); - return false; - } - try { - System.out.println(System.getProperty("user.dir")); - } catch (Exception e) { - return false; - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandRm.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandRm.java deleted file mode 100644 index a1f04b901..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandRm.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -public class CommandRm extends Command { - public CommandRm() { - name = "rm"; - numberOfArguments = 3; - } - - @Override - public boolean run(final String[] arguments) { - if (arguments.length != numberOfArguments - & arguments.length != numberOfArguments - 1) { - System.out.println("wrong number of arguments"); - return false; - } - boolean recursive = - (arguments.length == numberOfArguments & arguments[1].equals("-r")); - boolean result; - if (recursive) { - result = recursiveDelete(arguments); - } else { - result = generalDelete(arguments); - } - return result; - } - - private boolean generalDelete(final String[] arguments) { - if (numberOfArguments - 1 != arguments.length) { - System.out.println("wrong number of arguments"); - return false; - } - Path filePath = PathsFunction.toAbsolutePathString(arguments[1]); - try { - if (!Files.deleteIfExists(filePath)) { - System.out.println(name + ": cannot remove \'" + arguments[1] + "\'" - + ": No such file or directory"); - return false; - } - } catch (Exception e) { - if (Files.isDirectory(filePath)) { - System.out.println(name + ": " + arguments[1] + ": is a directory"); - } - return false; - } - return true; - } - - private boolean recursiveDelete(final String[] arguments) { - Path dirPath = PathsFunction.toAbsolutePathString(arguments[2]); - FileVisitorDelete myFileVisitorDelete = new FileVisitorDelete(); - - try { - Files.walkFileTree(dirPath, myFileVisitorDelete); - } catch (IOException e) { - return false; - } - return true; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileUtils.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileUtils.java deleted file mode 100644 index 93e9fe233..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileUtils.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.nio.file.Files; -import java.nio.file.Path; - -public class FileUtils { - public static boolean mkdir(Path newDirectory) { - CommandMkdir command = new CommandMkdir(); - String[] args = {"mkdir", - newDirectory.toString() - }; - return command.run(args); - } - - public static boolean rmdir(Path newDirectory) { - CommandRm command = new CommandRm(); - if (!Files.isDirectory(newDirectory) | !Files.exists(newDirectory)) { - return false; - } - String[] args = {"rm", - "-r", - newDirectory.toString() - }; - return command.run(args); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileVisitorCopy.java b/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileVisitorCopy.java deleted file mode 100644 index b281dcfdd..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileVisitorCopy.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; - -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.SimpleFileVisitor; - -import static java.nio.file.FileVisitResult.*; - -import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; - -public class FileVisitorCopy extends SimpleFileVisitor { - private final Path startPath; - private final Path destinationPath; - - public FileVisitorCopy(final Path newStartPath, final Path newDestinationPath) { - startPath = newStartPath; - destinationPath = newDestinationPath; - } - - @Override - public FileVisitResult visitFile(final Path filePath, final BasicFileAttributes attr) { - Path newFilePath = destinationPath.resolve(startPath.relativize(filePath)); - try { - Files.copy(filePath, newFilePath); - } catch (IOException e) { - System.err.println("IOException: " + filePath.toAbsolutePath()); - } - return CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(final Path filePath, IOException exc) { - System.err.println("Error occuried while visitтпg file"); - return CONTINUE; - } - - @Override - public FileVisitResult preVisitDirectory(final Path dirPath, BasicFileAttributes attr) { - Path newDirPath = destinationPath.resolve(startPath.relativize(dirPath)); - try { - Files.createDirectory(newDirPath); - } catch (IOException e) { - System.err.println("IOException"); - } - return CONTINUE; - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/TestStoreable.java b/src/ru/fizteh/fivt/students/titov/JUnit/TestStoreable.java new file mode 100644 index 000000000..3f75e4827 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/JUnit/TestStoreable.java @@ -0,0 +1,109 @@ +package ru.fizteh.fivt.students.titov.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import ru.fizteh.fivt.storage.structured.*; +import ru.fizteh.fivt.students.titov.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.shell.FileUtils; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class TestStoreable { + static String providerDirectory; + static String tableName; + static TableProviderFactory factory; + static TableProvider provider; + static Table table; + static Storeable entry; + static List> typeList; + + @Before + public void setUp() throws Exception { + providerDirectory = Paths.get("").resolve("provider").toString(); + tableName = "testTable2"; + factory = new MFileHashMapFactory(); + typeList = new ArrayList<>(); + typeList.add(Integer.class); + typeList.add(String.class); + try { + provider = factory.create(providerDirectory); + table = provider.createTable(tableName, typeList); + entry = provider.createFor(table); + } catch (IOException e) { + //suppress + } + } + + @After + public void tearDown() throws Exception { + try { + FileUtils.rmdir(Paths.get(providerDirectory)); + } catch (IOException e) { + //suppress + } + FileUtils.mkdir(Paths.get(providerDirectory)); + } + + @Test + public void testSetColumnAt() throws Exception { + entry.setColumnAt(0, null); + boolean exceptionWas = false; + try { + entry.setColumnAt(0, "new"); + } catch (ColumnFormatException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + exceptionWas = false; + try { + entry.setColumnAt(2, "new"); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } + + @Test + public void testGetColumnAt() throws Exception { + entry.setColumnAt(0, 1); + assertEquals((entry.getColumnAt(0)), 1); + + boolean exceptionWas = false; + try { + entry.getColumnAt(2); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } + + @Test + public void testGetIntAt() throws Exception { + entry.setColumnAt(0, 1); + entry.setColumnAt(1, "new"); + assertTrue(entry.getIntAt(0).equals(1)); + + boolean exceptionWas = false; + try { + entry.getIntAt(1); + } catch (ColumnFormatException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + + exceptionWas = false; + try { + entry.getIntAt(100); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/TestTable.java b/src/ru/fizteh/fivt/students/titov/JUnit/TestTable.java new file mode 100644 index 000000000..ebc8dfd3a --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/JUnit/TestTable.java @@ -0,0 +1,259 @@ +package ru.fizteh.fivt.students.titov.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import ru.fizteh.fivt.storage.structured.*; +import ru.fizteh.fivt.students.titov.file_map.FileMap; +import ru.fizteh.fivt.students.titov.multi_file_hash_map.MFileHashMapFactory; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class TestTable { + String key; + Storeable value; + Storeable newValue; + String providerDirectory; + String tableName; + String newTableName; + + Table testTable; + Table newTestTable; + TableProvider provider; + TableProviderFactory factory; + + static List> typeList; + static List> newTypeList; + + + @BeforeClass + public static void setUpBeforeClass() { + typeList = new ArrayList<>(); + typeList.add(Integer.class); + typeList.add(String.class); + typeList.add(Boolean.class); + + newTypeList = new ArrayList<>(); + newTypeList.add(Double.class); + newTypeList.add(Byte.class); + newTypeList.add(Float.class); + } + + @Before + public void setUp() { + key = "key"; + providerDirectory = Paths.get("").resolve("provider").toString(); + tableName = "testTable"; + newTableName = "newTestTable"; + factory = new MFileHashMapFactory(); + try { + provider = factory.create(providerDirectory); + testTable = provider.createTable(tableName, typeList); + newTestTable = provider.createTable(newTableName, newTypeList); + } catch (IOException e) { + //suppress + } + value = provider.createFor(testTable); + newValue = provider.createFor(testTable); + + value.setColumnAt(0, 100); + value.setColumnAt(1, "qwerty"); + value.setColumnAt(2, true); + + newValue.setColumnAt(0, 585); + newValue.setColumnAt(1, "newQwerty"); + newValue.setColumnAt(2, false); + } + + @After + public void tearDown() { + try { + provider.removeTable(tableName); + provider.removeTable(newTableName); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testGetName() throws Exception { + assertEquals(testTable.getName(), tableName); + } + + @Test + public void testGet() throws Exception { + assertNull(testTable.get(key)); + testTable.put(key, value); + assertEquals(testTable.get(key), value); + testTable.put(key, newValue); + assertEquals(testTable.get(key), newValue); + testTable.remove(key); + assertNull(testTable.get(key)); + testTable.rollback(); + + testTable.put(key, value); + testTable.commit(); + testTable.put(key, newValue); + assertEquals(testTable.get(key), newValue); + testTable.remove(key); + assertNull(testTable.get(key)); + } + + @Test + public void testRemove() throws Exception { + assertNull(testTable.remove(key)); + testTable.put(key, value); + assertEquals(testTable.remove(key), value); + + testTable.rollback(); + testTable.put(key, value); + assertEquals(testTable.remove(key), value); + testTable.put(key, value); + testTable.commit(); + assertEquals(testTable.remove(key), value); + assertNull(testTable.remove(key)); + } + + @Test + public void testPutCorrectValue() throws Exception { + assertNull(testTable.put(key, value)); + assertEquals(testTable.put(key, value), value); + assertEquals(testTable.get(key), value); + assertEquals(testTable.put(key, newValue), value); + assertEquals(testTable.get(key), newValue); + testTable.remove(key); + assertNull(testTable.put(key, value)); + + String keyForCommit = "keyCM"; + Storeable valueForCommit = ((FileMap) testTable).getTableProvider().createFor(testTable); + valueForCommit.setColumnAt(0, 999); + valueForCommit.setColumnAt(1, "commit-value"); + valueForCommit.setColumnAt(2, false); + + int size = 5; + for (int i = 0; i < size; ++i) { + valueForCommit.setColumnAt(0, 999 + i); + assertNull(testTable.put(keyForCommit + i, valueForCommit)); + } + testTable.commit(); + for (int i = 0; i < size; ++i) { + valueForCommit.setColumnAt(0, 999 + i); + assertEquals(testTable.get(keyForCommit + i), valueForCommit); + } + + Storeable freshValue = ((FileMap) testTable).getTableProvider().createFor(testTable); + freshValue.setColumnAt(0, 123456); + freshValue.setColumnAt(1, "FRESH!!!"); + freshValue.setColumnAt(2, true); + + testTable.rollback(); + testTable.remove(keyForCommit + 1); + + valueForCommit.setColumnAt(0, 1000); + assertNull(testTable.put(keyForCommit + 1, valueForCommit)); + valueForCommit.setColumnAt(0, 1001); + assertEquals(testTable.put(keyForCommit + 2, freshValue), valueForCommit); + + Storeable changedFreshValue = freshValue; + changedFreshValue.setColumnAt(1, "CHANGED"); + assertEquals(testTable.put(keyForCommit + 2, changedFreshValue), freshValue); + } + + @Test + public void testSize() throws Exception { + int size = 5; + for (int i = 0; i < size; ++i) { + value.setColumnAt(0, i); + testTable.put(key + i, value); + } + assertEquals(testTable.size(), size); + testTable.remove(key + 0); + assertEquals(testTable.size(), size - 1); + } + + @Test + public void testRollback() throws Exception { + int size = 5; + for (int i = 0; i < size; ++i) { + value.setColumnAt(0, i); + testTable.put(key + i, value); + } + testTable.remove(key + 0); + testTable.remove(key + 2); + testTable.put(key + 1, newValue); + assertEquals(testTable.rollback(), size - 2); + testTable.put(key, value); + assertEquals(testTable.rollback(), 1); + testTable.put(key, value); + testTable.commit(); + assertEquals(testTable.rollback(), 0); + } + + @Test + public void testCommit() throws Exception { + int size = 5; + for (int i = 0; i < size; ++i) { + value.setColumnAt(0, i); + testTable.put(key + i, value); + } + testTable.remove(key + 0); + testTable.remove(key + 2); + testTable.put(key + 1, newValue); + assertEquals(testTable.commit(), size - 2); + assertEquals(testTable.rollback(), 0); + testTable.put(key, newValue); + testTable.remove(key); + assertEquals(testTable.commit(), 0); + newValue.setColumnAt(0, 111111); + testTable.put(key + 1, newValue); + assertEquals(testTable.commit(), 1); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetNullInput() { + testTable.get(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testPutNullInput() { + testTable.put(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void testRemoveNullInput() { + testTable.remove(null); + } + + @Test(expected = ColumnFormatException.class) + public void testPutIllegalColumn() { + Storeable newValueForCheck = provider.createFor(newTestTable); + newValueForCheck.setColumnAt(0, 4.4); + newValueForCheck.setColumnAt(1, (byte) 0); + newValueForCheck.setColumnAt(2, (float) 8.8); + testTable.put("simpleKey", newValueForCheck); + } + + @Test + public void testGetColumnsCount() { + assertEquals(testTable.getColumnsCount(), 3); + } + + @Test + public void testGetColumnType() { + assertEquals(testTable.getColumnType(0), Integer.class); + boolean exceptionWas = false; + try { + testTable.getColumnType(9); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/TestTableProvider.java b/src/ru/fizteh/fivt/students/titov/JUnit/TestTableProvider.java new file mode 100644 index 000000000..88802a4d6 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/JUnit/TestTableProvider.java @@ -0,0 +1,241 @@ +package ru.fizteh.fivt.students.titov.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import ru.fizteh.fivt.storage.structured.*; +import ru.fizteh.fivt.students.titov.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.storeable.TypesUtils; +import ru.fizteh.fivt.students.titov.shell.FileUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class TestTableProvider { + String providerDirectory; + String tableName; + TableProvider provider; + TableProviderFactory factory; + + static List> typeList; + static List> wrongTypeList; + + @BeforeClass + public static void setUpBeforeClass() { + typeList = new ArrayList<>(); + typeList.add(Integer.class); + typeList.add(String.class); + + wrongTypeList = new ArrayList<>(); + wrongTypeList.add(Integer.class); + wrongTypeList.add(String.class); + wrongTypeList.add(Double.class); + } + + @Before + public void setUp() { + providerDirectory = Paths.get("").resolve("provider").toString(); + tableName = "testTable"; + factory = new MFileHashMapFactory(); + try { + provider = factory.create(providerDirectory); + } catch (IOException e) { + //suppress + } + } + + @After + public void tearDown() { + try { + FileUtils.rmdir(Paths.get(providerDirectory)); + } catch (IOException e) { + //suppress + } + FileUtils.mkdir(Paths.get(providerDirectory)); + } + + @Test + public void testGetTable() throws Exception { + assertNull(provider.getTable(tableName)); + assertNotNull(provider.createTable(tableName, typeList)); + assertNotNull(provider.getTable(tableName)); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetTableNull() throws Exception { + provider.getTable(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTableDirExists() throws Exception { + FileUtils.mkdir(Paths.get(providerDirectory, tableName)); + provider.createTable(tableName, typeList); + } + + @Test + public void testCreateDouble() throws Exception { + provider.createTable(tableName, typeList); + assertNull(provider.createTable(tableName, typeList)); + } + + @Test + public void testCreateTableDirNotExists() throws Exception { + try { + FileUtils.rmdir(Paths.get(providerDirectory, tableName)); + } catch (IllegalArgumentException e) { + //suppress - means directory doesn't exist + } + assertNotNull(provider.createTable(tableName, typeList)); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTableNullDirectory() throws Exception { + provider.createTable(null, typeList); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTableNullTypeList() throws Exception { + provider.createTable(tableName, null); + } + + @Test + public void testRemoveTableExists() throws Exception { + provider.createTable(tableName, typeList); + provider.removeTable(tableName); + assertNull(provider.getTable(tableName)); + assertTrue(!Files.exists(Paths.get(providerDirectory, tableName))); + } + + @Test(expected = IllegalStateException.class) + public void testRemoveTableNotExists() throws Exception { + provider.removeTable(tableName); + } + + @Test(expected = IllegalArgumentException.class) + public void testRemoveTableNull() throws Exception { + provider.removeTable(null); + } + + @Test + public void testSerialize() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + Storeable value = provider.createFor(newTable); + value.setColumnAt(0, 100); + value.setColumnAt(1, "example"); + + String serValue = "100example"; + assertEquals(provider.serialize(newTable, value), serValue); + + Table wrongTable; + wrongTable = provider.createTable(tableName + 2, wrongTypeList); + Storeable wrongValue = provider.createFor(wrongTable); + wrongValue.setColumnAt(0, 100); + wrongValue.setColumnAt(1, "example"); + wrongValue.setColumnAt(2, 5.5); + + boolean exceptionWas = false; + try { + provider.serialize(newTable, wrongValue); + } catch (ColumnFormatException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testDeserialize() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + String stringForParse = "100example"; + String stringForParse2 = "qwertyexample"; + try { + Storeable deserValue = provider.deserialize(newTable, stringForParse); + assertTrue(deserValue.getIntAt(0).equals(100)); + assertEquals(deserValue.getStringAt(1), "example"); + } catch (ParseException e) { + assertNotNull(null); + } + + boolean exceptionWas = false; + try { + provider.deserialize(newTable, stringForParse + 2); + } catch (ParseException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + + exceptionWas = false; + try { + provider.deserialize(newTable, stringForParse2); + } catch (ParseException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testCreateFor() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + Storeable temp = provider.createFor(newTable); + assertEquals(TypesUtils.getSizeOfStoreable(temp), newTable.getColumnsCount()); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testCreateForWithValue() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + List value = new ArrayList<>(); + value.add(100); + value.add("new"); + Storeable temp = provider.createFor(newTable, value); + assertEquals(TypesUtils.getSizeOfStoreable(temp), newTable.getColumnsCount()); + boolean exceptionWas = false; + + try { + value = new ArrayList<>(); + value.add("new"); + value.add(100); + provider.createFor(newTable, value); + } catch (ColumnFormatException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + + exceptionWas = false; + try { + value = new ArrayList<>(); + value.add("new2"); + provider.createFor(newTable, value); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + + } catch (IOException e) { + //suppress + } + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTableProviderFactory.java b/src/ru/fizteh/fivt/students/titov/JUnit/TestTableProviderFactory.java similarity index 58% rename from src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTableProviderFactory.java rename to src/ru/fizteh/fivt/students/titov/JUnit/TestTableProviderFactory.java index f360e79fd..6b1aa3512 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTableProviderFactory.java +++ b/src/ru/fizteh/fivt/students/titov/JUnit/TestTableProviderFactory.java @@ -1,12 +1,14 @@ -package ru.fizteh.fivt.students.titov.JUnit.TestsPackage; +package ru.fizteh.fivt.students.titov.junit; import org.junit.After; import org.junit.Before; import org.junit.Test; -import ru.fizteh.fivt.storage.strings.TableProviderFactory; -import ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage.MFileHashMapFactory; -import ru.fizteh.fivt.students.titov.JUnit.ShellPackage.FileUtils; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; +import ru.fizteh.fivt.students.titov.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.shell.FileUtils; + +import java.io.IOException; import java.nio.file.Paths; import static org.junit.Assert.*; @@ -23,16 +25,25 @@ public void setUp() { @After public void tearDown() { - FileUtils.rmdir(Paths.get(dir)); - FileUtils.mkdir(Paths.get(dir)); + try { + FileUtils.rmdir(Paths.get(dir)); + FileUtils.mkdir(Paths.get(dir)); + } catch (IOException e) { + //suppress + } } @Test public void testCreateDirExists() throws Exception { FileUtils.mkdir(Paths.get(dir)); - assertNotNull(testFactory.create(dir)); + try { + assertNotNull(testFactory.create(dir)); + } catch (IOException e) { + assertTrue(false); + } } + @Test public void testCreateDirNotExists() throws Exception { assertNotNull(testFactory.create(dir)); diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTable.java b/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTable.java deleted file mode 100644 index f5b0fdacb..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTable.java +++ /dev/null @@ -1,189 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.TestsPackage; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import ru.fizteh.fivt.storage.strings.Table; -import ru.fizteh.fivt.storage.strings.TableProvider; -import ru.fizteh.fivt.storage.strings.TableProviderFactory; -import ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage.MFileHashMapFactory; - -import java.nio.file.Paths; -import java.util.List; - -import static org.junit.Assert.*; - -public class TestTable { - String key; - String value; - String newValue; - String providerDirectory; - String tableName; - - Table testTable; - TableProvider provider; - TableProviderFactory factory; - - @Before - public void setUp() { - key = "key"; - value = "value"; - newValue = "newvalue"; - providerDirectory = Paths.get("").resolve("provider").toString(); - tableName = "testTable"; - factory = new MFileHashMapFactory(); - provider = factory.create(providerDirectory); - testTable = provider.createTable(tableName); - } - - @After - public void tearDown() { - provider.removeTable(tableName); - } - - @Test - public void testGetName() throws Exception { - assertTrue(testTable.getName().equals(tableName)); - } - - @Test - public void testGet() throws Exception { - assertNull(testTable.get(key)); - testTable.put(key, value); - assertTrue(testTable.get(key).equals(value)); - testTable.put(key, newValue); - assertTrue(testTable.get(key).equals(newValue)); - testTable.remove(key); - assertNull(testTable.get(key)); - testTable.rollback(); - - testTable.put(key, value); - testTable.commit(); - testTable.put(key, newValue); - assertTrue(testTable.get(key).equals(newValue)); - testTable.remove(key); - assertNull(testTable.get(key)); - } - - @Test - public void testRemove() throws Exception { - assertNull(testTable.remove(key)); - testTable.put(key, value); - assertTrue(testTable.remove(key).equals(value)); - - testTable.rollback(); - testTable.put(key, value); - assertTrue(testTable.remove(key).equals(value)); - testTable.put(key, value); - testTable.commit(); - assertTrue(testTable.remove(key).equals(value)); - assertNull(testTable.remove(key)); - } - - @Test - public void testPut() throws Exception { - assertNull(testTable.put(key, value)); - assertTrue(testTable.put(key, value).equals(value)); - assertTrue(testTable.get(key).equals(value)); - assertTrue(testTable.put(key, newValue).equals(value)); - assertTrue(testTable.get(key).equals(newValue)); - testTable.remove(key); - assertNull(testTable.put(key, value)); - - String keyForCommit = "keyCM"; - String valueForCommit = "vakueCM"; - int size = 5; - for (int i = 0; i < size; ++i) { - assertNull(testTable.put(keyForCommit + i, valueForCommit + i)); - } - testTable.commit(); - for (int i = 0; i < size; ++i) { - assertTrue(testTable.get(keyForCommit + i).equals(valueForCommit + i)); - } - - String freshValue = "addValue"; - testTable.rollback(); - testTable.remove(keyForCommit + 1); - assertNull(testTable.put(keyForCommit + 1, valueForCommit + 1)); - assertTrue(testTable.put(keyForCommit + 2, freshValue).equals(valueForCommit + 2)); - assertTrue(testTable.put(keyForCommit + 2, freshValue + "*").equals(freshValue)); - } - - @Test - public void testSize() throws Exception { - int size = 5; - for (int i = 0; i < size; ++i) { - testTable.put(key + i, value + i); - } - assertTrue(testTable.size() == size); - testTable.remove(key + 0); - assertTrue(testTable.size() == size - 1); - } - - @Test - public void testRollback() throws Exception { - int size = 5; - for (int i = 0; i < size; ++i) { - testTable.put(key + i, value + i); - } - testTable.remove(key + 0); - testTable.remove(key + 2); - testTable.put(key + 1, newValue); - assertTrue(testTable.rollback() == size - 2); - testTable.put(key, value); - assertTrue(testTable.rollback() == 1); - testTable.put(key, value); - testTable.commit(); - assertTrue(testTable.rollback() == 0); - } - - @Test - public void testCommit() throws Exception { - int size = 5; - for (int i = 0; i < size; ++i) { - testTable.put(key + i, value + i); - } - testTable.remove(key + 0); - testTable.remove(key + 2); - testTable.put(key + 1, newValue); - assertTrue(testTable.commit() == size - 2); - assertTrue(testTable.rollback() == 0); - testTable.put(key, newValue); - testTable.remove(key); - assertTrue(testTable.commit() == 0); - testTable.put(key + 1, newValue + 2); - assertTrue(testTable.commit() == 1); - } - - @Test - public void testList() throws Exception { - int size = 5; - for (int i = 0; i < size; ++i) { - testTable.put(key + i, value + i); - } - boolean theSame = true; - List testList = testTable.list(); - for (int i = 0; i < size; ++i) { - if (!testList.contains(key + i)) { - theSame = false; - } - } - testTable.remove(key + 4); - testTable.remove(key + 3); - testList = testTable.list(); - for (int i = 0; i < size - 2; ++i) { - if (!testList.contains(key + i)) { - theSame = false; - } - } - assertTrue(theSame); - } - - @Test(expected = IllegalArgumentException.class) - public void nullInput() { - testTable.get(null); - testTable.remove(null); - testTable.put(null, value); - testTable.put(key, null); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTableProvider.java b/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTableProvider.java deleted file mode 100644 index 7a7832e45..000000000 --- a/src/ru/fizteh/fivt/students/titov/JUnit/TestsPackage/TestTableProvider.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.fizteh.fivt.students.titov.JUnit.TestsPackage; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import ru.fizteh.fivt.storage.strings.TableProvider; -import ru.fizteh.fivt.storage.strings.TableProviderFactory; -import ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage.MFileHashMapFactory; -import ru.fizteh.fivt.students.titov.JUnit.ShellPackage.FileUtils; - -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.junit.Assert.*; - -public class TestTableProvider { - String providerDirectory; - String tableName; - TableProvider provider; - TableProviderFactory factory; - - @Before - public void setUp() { - providerDirectory = Paths.get("").resolve("provider").toString(); - tableName = "testTable"; - factory = new MFileHashMapFactory(); - provider = factory.create(providerDirectory); - } - - @After - public void tearDown() { - FileUtils.rmdir(Paths.get(providerDirectory)); - FileUtils.mkdir(Paths.get(providerDirectory)); - } - - @Test - public void testGetTable() throws Exception { - assertNull(provider.getTable(tableName)); - assertNotNull(provider.createTable(tableName)); - assertNotNull(provider.getTable(tableName)); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetTableNull() throws Exception { - provider.getTable(null); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateTableDirExists() throws Exception { - FileUtils.mkdir(Paths.get(providerDirectory, tableName)); - provider.createTable(tableName); - } - - @Test - public void testCreateDouble() throws Exception { - provider.createTable(tableName); - assertNull(provider.createTable(tableName)); - } - - @Test - public void testCreateTableDirNotExists() throws Exception { - FileUtils.rmdir(Paths.get(providerDirectory, tableName)); - assertNotNull(provider.createTable(tableName)); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateTableNull() throws Exception { - provider.createTable(null); - } - - @Test - public void testRemoveTableDirExists() throws Exception { - provider.createTable(tableName); - provider.removeTable(tableName); - assertNull(provider.getTable(tableName)); - assertTrue(!Files.exists(Paths.get(providerDirectory, tableName))); - } - - @Test(expected = IllegalStateException.class) - public void testRemoveTableDirNotExists() throws Exception { - FileUtils.rmdir(Paths.get(providerDirectory, tableName)); - provider.removeTable(tableName); - } - - @Test(expected = IllegalArgumentException.class) - public void testRemoveTableNull() throws Exception { - provider.removeTable(null); - } -} diff --git a/src/ru/fizteh/fivt/students/titov/file_map/BadFileException.java b/src/ru/fizteh/fivt/students/titov/file_map/BadFileException.java new file mode 100644 index 000000000..650aabd5d --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/file_map/BadFileException.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.titov.file_map; + +import java.io.IOException; + +public class BadFileException extends IOException { + public BadFileException(Throwable cause) { + super(cause); + } + + public BadFileException() { + super("Can't read from disk"); + } + + @Override + public String getMessage() { + Throwable cause = getCause(); + return cause.getClass().getName() + ": " + cause.getMessage(); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/Command.java b/src/ru/fizteh/fivt/students/titov/file_map/Command.java similarity index 80% rename from src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/Command.java rename to src/ru/fizteh/fivt/students/titov/file_map/Command.java index ad1a0f21a..4f353b13b 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/Command.java +++ b/src/ru/fizteh/fivt/students/titov/file_map/Command.java @@ -1,4 +1,4 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; +package ru.fizteh.fivt.students.titov.file_map; public abstract class Command { protected String name; diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FileMap.java b/src/ru/fizteh/fivt/students/titov/file_map/FileMap.java similarity index 60% rename from src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FileMap.java rename to src/ru/fizteh/fivt/students/titov/file_map/FileMap.java index faef4ed93..b015ebfc3 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/FileMap.java +++ b/src/ru/fizteh/fivt/students/titov/file_map/FileMap.java @@ -1,6 +1,10 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; +package ru.fizteh.fivt.students.titov.file_map; -import ru.fizteh.fivt.storage.strings.Table; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.students.titov.storeable.TypesUtils; +import ru.fizteh.fivt.students.titov.storeable.Serializator; import java.io.*; import java.nio.ByteBuffer; @@ -9,54 +13,76 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.text.ParseException; import java.util.*; public class FileMap implements Table { - private static final int MAXNUMBEROFDIRS = 16; - private static final int MAXNUMBEROFFILES = 16; - private HashMap stableData; - private HashMap addedData; - private HashMap changedData; - private HashSet removedData; + private static final int MAX_NUMBER_OF_DIRS = 16; + private static final int MAX_NUMBER_OF_FILES = 16; + private static final String SUFFIX_OF_DIRECTORY = ".dir"; + private static final String SUFFIX_OF_FILE = ".dat"; + private static final String FILE_ENCODING = "UTF-8"; + private Map stableData; + private Map addedData; + private Map changedData; + private Set removedData; + private List> typeList; + private int numberOfColumns; private String directoryOfTable; + private TableProvider parent; private int getNumberOfDirectory(int hash) { - int result = hash % MAXNUMBEROFDIRS; + int result = hash % MAX_NUMBER_OF_DIRS; if (result < 0) { - result += MAXNUMBEROFDIRS; + result += MAX_NUMBER_OF_DIRS; } return result; } private int getNumberOfFile(int hash) { - int result = hash / MAXNUMBEROFDIRS % MAXNUMBEROFFILES; + int result = hash / MAX_NUMBER_OF_DIRS % MAX_NUMBER_OF_FILES; if (result < 0) { - result += MAXNUMBEROFFILES; + result += MAX_NUMBER_OF_FILES; } return result; } - private void clearStaff() { + private void clearAll() { removedData.clear(); addedData.clear(); changedData.clear(); } - public FileMap(String newDirectoryFile) { - directoryOfTable = newDirectoryFile; + /** + * Create empty Filemap + * + * @param newDirectory - directory of this file_map + * @param newTypeList - list of types (signature of table) + */ + public FileMap(String newDirectory, List> newTypeList, TableProvider newParent) { + directoryOfTable = newDirectory; stableData = new HashMap<>(); addedData = new HashMap<>(); changedData = new HashMap<>(); removedData = new HashSet<>(); + typeList = newTypeList; + numberOfColumns = typeList.size(); + parent = newParent; } + public TableProvider getTableProvider() { + return parent; + } + + @Override public String getName() { return Paths.get(directoryOfTable).getFileName().toString(); } - public String get(String key) throws IllegalArgumentException { + @Override + public Storeable get(String key) throws IllegalArgumentException { if (key == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("null argument"); } if (removedData.contains(key)) { return null; @@ -70,9 +96,10 @@ public String get(String key) throws IllegalArgumentException { return stableData.get(key); } - public String remove(String key) throws IllegalArgumentException { + @Override + public Storeable remove(String key) throws IllegalArgumentException { if (key == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("null argument"); } if (removedData.contains(key)) { return null; @@ -90,10 +117,13 @@ public String remove(String key) throws IllegalArgumentException { return stableData.get(key); } - public String put(String key, String value) throws IllegalArgumentException { + @Override + public Storeable put(String key, Storeable value) throws IllegalArgumentException { if (key == null || value == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("null argument"); } + TypesUtils.checkNewStorableValue(typeList, value); + boolean wasDeleted = false; if (removedData.contains(key)) { removedData.remove(key); @@ -119,42 +149,55 @@ public String put(String key, String value) throws IllegalArgumentException { } } + @Override public int size() { return stableData.size() + addedData.size() - removedData.size(); } + @Override + public int getColumnsCount() { + return numberOfColumns; + } + + @Override + public Class getColumnType(int columnIndex) throws IndexOutOfBoundsException { + return typeList.get(columnIndex); + } + + @Override public int rollback() { - int result = getNumberOfUncommitedChanges(); - clearStaff(); + int result = changedData.size() + removedData.size() + addedData.size(); + clearAll(); return result; } - public int commit() { + @Override + public int commit() throws IOException { int result = changedData.size() + removedData.size() + addedData.size(); stableData.keySet().removeAll(removedData); stableData.putAll(changedData); stableData.putAll(addedData); boolean allRight = true; if (changedData.size() + removedData.size() > 0) { - Set reloadKeys = removedData; - reloadKeys.addAll(changedData.keySet()); - for (String oneKey : reloadKeys) { - if (!load(oneKey, false)) { + Set resaveKeys = removedData; + resaveKeys.addAll(changedData.keySet()); + for (String oneKey : resaveKeys) { + if (!save(oneKey, false)) { allRight = false; } } } for (String oneKey : addedData.keySet()) { - if (!load(oneKey, true)) { + if (!save(oneKey, true)) { allRight = false; } } - clearStaff(); + clearAll(); if (allRight) { return result; } else { - return -1; + throw new IOException(); } } @@ -165,28 +208,29 @@ public List list() { return keyList; } - public int getNumberOfUncommitedChanges() { + @Override + public int getNumberOfUncommittedChanges() { return addedData.size() + changedData.size() + removedData.size(); } - public boolean init() { + public boolean init() throws BadFileException { String[] listOfDirectories = new File(directoryOfTable).list(); if (listOfDirectories == null) { return true; } - for (String oneDirectory: listOfDirectories) { - String currentDirectory = directoryOfTable + System.getProperty("file.separator") - + oneDirectory; + for (String directory: listOfDirectories) { + String currentDirectory = directoryOfTable + File.separator + + directory; if (!Files.isDirectory(Paths.get(currentDirectory))) { continue; } String[] listOfFiles = new File(currentDirectory).list(); for (String oneFile : listOfFiles) { - String currentFile = currentDirectory + System.getProperty("file.separator") + String currentFile = currentDirectory + File.separator + oneFile; - int numberOfDirectory = oneDirectory.charAt(0) - '0'; - if (oneDirectory.charAt(1) != '.') { - numberOfDirectory = 10 * numberOfDirectory + oneDirectory.charAt(1) - '0'; + int numberOfDirectory = directory.charAt(0) - '0'; + if (directory.charAt(1) != '.') { + numberOfDirectory = 10 * numberOfDirectory + directory.charAt(1) - '0'; } int numberOfFile = oneFile.charAt(0) - '0'; if (oneFile.charAt(1) != '.') { @@ -200,8 +244,7 @@ public boolean init() { bufferFromDisk = inputChannel.map(MapMode.READ_ONLY, 0, inputChannel.size()); } catch (IOException e) { - System.out.println("io exception"); - return false; + throw new BadFileException(e); } try { while (bufferFromDisk.hasRemaining()) { @@ -216,6 +259,10 @@ public boolean init() { throw new BadFileException(); } + if (keySize < 0) { + throw new BadFileException(); + } + if (bufferFromDisk.remaining() >= keySize) { bufferFromDisk.get(key, 0, key.length); } else { @@ -224,6 +271,9 @@ public boolean init() { if (bufferFromDisk.remaining() >= 4) { valueSize = bufferFromDisk.getInt(); + if (valueSize < 0) { + throw new BadFileException(); + } value = new byte[valueSize]; } else { throw new BadFileException(); @@ -234,38 +284,40 @@ public boolean init() { throw new BadFileException(); } - String keyString = new String(key, "UTF-8"); + String keyString = new String(key, FILE_ENCODING); if (getNumberOfDirectory(keyString.hashCode()) != numberOfDirectory || getNumberOfFile(keyString.hashCode()) != numberOfFile) { throw new BadFileException(); } try { - stableData.put(new String(key, "UTF-8"), new String(value, "UTF-8")); + stableData.put(new String(key, FILE_ENCODING), + Serializator.deserialize(this, new String(value, "UTF-8"))); } catch (UnsupportedEncodingException e) { - System.out.println("unsupported encoding"); - return false; + throw new BadFileException(e); + } catch (ParseException e) { + throw new BadFileException(e); } } } catch (NullPointerException e) { - System.out.println("null pointer exception"); + throw new BadFileException(e); } } catch (FileNotFoundException e) { - System.out.println("file not found"); - return false; + throw new BadFileException(e); } catch (BadFileException e) { - System.out.println("problems with database file"); - return false; + throw new BadFileException(e); } catch (IOException e) { - System.out.println("io exception"); - return false; + throw new BadFileException(e); } } } return true; } - public boolean load(String key, boolean appendFile) { + /** + * Returns True if the record on the disc was successful and otherwise False. + */ + public boolean save(String key, boolean appendFile) throws BadFileException { HashSet keySet = new HashSet<>(); ByteBuffer bufferForSize = ByteBuffer.allocate(4); @@ -284,77 +336,74 @@ public boolean load(String key, boolean appendFile) { } } - Path directoryForLoad; - Path fileForLoad; - directoryForLoad = Paths.get(directoryOfTable, numberOfDirectory + ".dir"); - if (!Files.exists(directoryForLoad)) { + Path directoryForsave; + Path fileForsave; + directoryForsave = Paths.get(directoryOfTable, numberOfDirectory + SUFFIX_OF_DIRECTORY); + if (!Files.exists(directoryForsave)) { try { - Files.createDirectory(directoryForLoad); + Files.createDirectory(directoryForsave); } catch (IOException e) { - System.out.println("error while creating directory for load"); + System.err.println("error while creating directory for save"); return false; } } - fileForLoad = Paths.get(directoryForLoad.toString(), numberOfFile + ".dat"); - if (!Files.exists(fileForLoad)) { + fileForsave = Paths.get(directoryForsave.toString(), numberOfFile + SUFFIX_OF_FILE); + if (!Files.exists(fileForsave)) { try { - Files.createFile(fileForLoad); + Files.createFile(fileForsave); } catch (IOException e) { - System.out.println("error while creating file for load"); + System.err.println("error while creating file for save"); return false; } } try (FileOutputStream outputStream - = new FileOutputStream(fileForLoad.toString(), appendFile)) { + = new FileOutputStream(fileForsave.toString(), appendFile)) { for (String oneKey : keySet) { try { byte[] keyByte = oneKey.getBytes("UTF-8"); - byte[] valueByte = stableData.get(oneKey).getBytes("UTF-8"); + byte[] valueByte = Serializator.serialize(this, stableData.get(oneKey)).getBytes("UTF-8"); outputStream.write(bufferForSize.putInt(0, keyByte.length).array()); outputStream.write(keyByte); outputStream.write(bufferForSize.putInt(0, valueByte.length).array()); outputStream.write(valueByte); } catch (UnsupportedEncodingException e) { - System.out.println("unsupported encoding"); + System.err.println("unsupported encoding"); return false; } catch (IOException e) { - System.out.println("io exception"); + System.err.println("io exception"); return false; } } } catch (FileNotFoundException e) { - System.out.println("file not found"); + System.err.println("file not found"); return false; } catch (IOException e) { - System.out.println("io exception"); + System.err.println("io exception"); return false; } if (!appendFile) { - deleteEmptyFiles(directoryForLoad, fileForLoad); + deleteEmptyFiles(directoryForsave, fileForsave); } return true; } - - public boolean deleteEmptyFiles(Path directory, Path file) { + public boolean deleteEmptyFiles(Path directory, Path file) throws BadFileException { try { if (Files.size(file) == 0) { Files.delete(file); } } catch (IOException e) { - System.err.println("error while deleting data base file"); - return false; + throw new BadFileException(e); } String[] listOfFiles = new File(directory.toString()).list(); if (listOfFiles.length == 0) { try { Files.delete(directory); } catch (IOException e) { - System.err.println("error while deleting directory"); - return false; + throw new BadFileException(e); } } return true; diff --git a/src/ru/fizteh/fivt/students/titov/file_map/FileMapCommand.java b/src/ru/fizteh/fivt/students/titov/file_map/FileMapCommand.java new file mode 100644 index 000000000..09f631bc7 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/file_map/FileMapCommand.java @@ -0,0 +1,8 @@ +package ru.fizteh.fivt.students.titov.file_map; + +public abstract class FileMapCommand extends Command { + public void initialize(String commandName, int n) { + name = commandName; + numberOfArguments = n; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/file_map/GetFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/file_map/GetFileMapCommand.java new file mode 100644 index 000000000..9af618af3 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/file_map/GetFileMapCommand.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.titov.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.titov.storeable.Serializator; + +public class GetFileMapCommand extends FileMapCommand { + public GetFileMapCommand() { + initialize("get", 2); + } + @Override + public boolean run(FileMap fileMap, String[] args) { + Storeable value = fileMap.get(args[1]); + if (value != null) { + System.err.println("found\n" + Serializator.serialize(fileMap, fileMap.get(args[1]))); + } else { + System.err.println("not found"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/file_map/ListFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/file_map/ListFileMapCommand.java new file mode 100644 index 000000000..69098ca47 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/file_map/ListFileMapCommand.java @@ -0,0 +1,16 @@ +package ru.fizteh.fivt.students.titov.file_map; + +import java.util.List; + +public class ListFileMapCommand extends FileMapCommand { + public ListFileMapCommand() { + initialize("list", 1); + } + + @Override + public boolean run(FileMap fileMap, String[] args) { + List allKeys = fileMap.list(); + System.out.println(String.join(", ", allKeys)); + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/file_map/PutFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/file_map/PutFileMapCommand.java new file mode 100644 index 000000000..dd45caa17 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/file_map/PutFileMapCommand.java @@ -0,0 +1,32 @@ +package ru.fizteh.fivt.students.titov.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.titov.storeable.Serializator; + +import java.text.ParseException; +import java.util.NoSuchElementException; + +public class PutFileMapCommand extends FileMapCommand { + public PutFileMapCommand() { + initialize("put", 2); + } + @Override + public boolean run(FileMap fileMap, String[] args) { + Storeable oldValue = fileMap.get(args[1]); + try { + fileMap.put(args[1], Serializator.deserialize(fileMap, args[2])); + } catch (ParseException e) { + System.out.println("wrong type (" + e.getMessage() + ")"); + return false; + } catch (NoSuchElementException e) { + System.err.println("error: not xml format value"); + return false; + } + if (oldValue != null) { + System.out.println("overwrite\n" + Serializator.serialize(fileMap, oldValue)); + } else { + System.out.println("new"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/file_map/RemoveFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/file_map/RemoveFileMapCommand.java new file mode 100644 index 000000000..5cbaf8a2e --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/file_map/RemoveFileMapCommand.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.titov.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; + +public class RemoveFileMapCommand extends FileMapCommand { + public RemoveFileMapCommand() { + initialize("remove", 2); + } + @Override + public boolean run(FileMap fileMap, String[] args) { + Storeable value = fileMap.remove(args[1]); + if (value != null) { + System.out.println("removed"); + } else { + System.out.println("not found"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/Shell.java b/src/ru/fizteh/fivt/students/titov/file_map/Shell.java similarity index 76% rename from src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/Shell.java rename to src/ru/fizteh/fivt/students/titov/file_map/Shell.java index 86df1576c..9d49a32a3 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/FileMapPackage/Shell.java +++ b/src/ru/fizteh/fivt/students/titov/file_map/Shell.java @@ -1,9 +1,10 @@ -package ru.fizteh.fivt.students.titov.JUnit.FileMapPackage; +package ru.fizteh.fivt.students.titov.file_map; import java.util.HashMap; import java.util.Scanner; public class Shell { + private static final String INVITATION = "$ "; private HashMap> shellCommands; private T objectForShell; @@ -17,7 +18,7 @@ public void addCommand(Command newCommand) { } public boolean interactiveMode() { - System.out.print("$ "); + System.out.print(INVITATION); boolean ended = false; boolean errorOccuried = false; @@ -32,6 +33,12 @@ public boolean interactiveMode() { } for (String oneCommand : parsedCommands) { parsedArguments = oneCommand.trim().split("\\s+"); + if (parsedArguments[0].equals("put")) { + if (oneCommand.contains("<")) { + String valueForPut = oneCommand.trim().substring(oneCommand.indexOf('<')); + parsedArguments[2] = valueForPut; + } + } if (parsedArguments.length == 0 || parsedArguments[0].equals("")) { continue; } @@ -41,19 +48,20 @@ public boolean interactiveMode() { } Command commandToExecute = shellCommands.get(parsedArguments[0]); if (commandToExecute != null) { - if (commandToExecute.numberOfArguments != parsedArguments.length) { - System.out.println(commandToExecute.name + " wrong number of arguments"); + if (commandToExecute.numberOfArguments != parsedArguments.length + & commandToExecute.numberOfArguments != -1) { + System.err.println(commandToExecute.name + ": wrong number of arguments"); errorOccuried = true; } else if (!commandToExecute.run(objectForShell, parsedArguments)) { errorOccuried = true; } } else { - System.out.println(parsedArguments[0] + ": command not found"); + System.err.println(parsedArguments[0] + ": command not found"); errorOccuried = true; } } if (!ended) { - System.out.print("$ "); + System.out.print(INVITATION); } } } @@ -85,17 +93,19 @@ public boolean batchMode(final String[] arguments) { } Command commandToExecute = shellCommands.get(parsedArguments[0]); if (commandToExecute != null) { - if (commandToExecute.numberOfArguments != parsedArguments.length) { - System.out.println(commandToExecute.name + " wrong number of arguments"); + if (commandToExecute.numberOfArguments != parsedArguments.length + & commandToExecute.numberOfArguments != -1) { + System.err.println(commandToExecute.name + " wrong number of arguments"); errorOccuried = true; } else if (!commandToExecute.run(objectForShell, parsedArguments)) { errorOccuried = true; } } else { - System.out.println(parsedArguments[0] + ": command not found"); + System.err.println(parsedArguments[0] + ": command not found"); errorOccuried = true; } } return !errorOccuried; } } + diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/CommitCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/CommitCommand.java new file mode 100644 index 000000000..3b65b1769 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/CommitCommand.java @@ -0,0 +1,27 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +import java.io.IOException; + +public class CommitCommand extends MultiFileHashMapCommand { + public CommitCommand() { + initialize("commit", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + isTable(currentTable); + } else { + try { + System.out.println(currentTable.commit()); + } catch (IOException e) { + System.err.println("io exception while writing in file"); + return false; + } + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/CreateCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/CreateCommand.java new file mode 100644 index 000000000..029a01f3f --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/CreateCommand.java @@ -0,0 +1,51 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.students.titov.storeable.TypesUtils; + +import java.io.IOException; +import java.util.List; + +public class CreateCommand extends MultiFileHashMapCommand { + public CreateCommand() { + initialize("create", -1); + } + + @Override + public boolean run(MFileHashMap myMultiDataBase, String[] args) { + StringBuilder simpleBuilder = new StringBuilder(); + for (int i = 2; i < args.length; ++i) { + if (i != 2) { + simpleBuilder.append(" "); + } + simpleBuilder.append(args[i]); + } + String concatArgs = simpleBuilder.toString(); + if (concatArgs.lastIndexOf("(") != 0 + || concatArgs.indexOf(")") != concatArgs.length() - 1) { + System.out.println("types should be in format: \" (type1 type2 ... typeN)\""); + return false; + } + + concatArgs = new String(concatArgs.toCharArray(), 1, concatArgs.length() - 2); + List> types; + try { + types = TypesUtils.toTypeList(concatArgs.split("\\s+")); + } catch (ColumnFormatException e) { + System.err.println(e.getMessage()); + return false; + } + try { + if (myMultiDataBase.createTable(args[1], types) != null) { + System.out.println("created"); + } else { + System.out.println("\'" + args[1] + "\' already exists"); + } + } catch (IOException e) { + return false; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/DropCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/DropCommand.java new file mode 100644 index 000000000..d092360e0 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/DropCommand.java @@ -0,0 +1,25 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import java.io.IOException; + +public class DropCommand extends MultiFileHashMapCommand { + public DropCommand() { + initialize("drop", 2); + } + + @Override + public boolean run(MFileHashMap myDataBase, String[] args) { + try { + myDataBase.removeTable(args[1]); + System.out.println("dropped"); + } catch (IOException e) { + System.err.println("io exception while removing directory"); + return false; + } catch (IllegalArgumentException e) { + System.err.println(e.getMessage()); + } catch (IllegalStateException e) { + System.err.println(e.getMessage()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ExitCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ExitCommand.java new file mode 100644 index 000000000..fb5a35324 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ExitCommand.java @@ -0,0 +1,13 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +public class ExitCommand extends MultiFileHashMapCommand { + public ExitCommand() { + initialize("exit", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + System.exit(0); + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/GetDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/GetDistributeCommand.java new file mode 100644 index 000000000..58842c26b --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/GetDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; +import ru.fizteh.fivt.students.titov.file_map.GetFileMapCommand; + +public class GetDistributeCommand extends MultiFileHashMapCommand { + public GetDistributeCommand() { + initialize("get", 2); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + GetFileMapCommand commandGet = new GetFileMapCommand(); + return commandGet.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ListDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ListDistributeCommand.java new file mode 100644 index 000000000..167d6bfc0 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ListDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; +import ru.fizteh.fivt.students.titov.file_map.ListFileMapCommand; + +public class ListDistributeCommand extends MultiFileHashMapCommand { + public ListDistributeCommand() { + initialize("list", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + ListFileMapCommand commandList = new ListFileMapCommand(); + return commandList.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MFileHashMap.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MFileHashMap.java new file mode 100644 index 000000000..5bfddd229 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MFileHashMap.java @@ -0,0 +1,182 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.text.ParseException; +import java.util.*; +import java.util.Map.Entry; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.titov.file_map.BadFileException; +import ru.fizteh.fivt.students.titov.file_map.FileMap; +import ru.fizteh.fivt.students.titov.storeable.AbstractStoreable; +import ru.fizteh.fivt.students.titov.storeable.TypesUtils; +import ru.fizteh.fivt.students.titov.storeable.Serializator; +import ru.fizteh.fivt.students.titov.shell.FileUtils; + +public class MFileHashMap implements TableProvider { + private String dataBaseDirectory; + private Map tables; + private FileMap currentTable; + public MFileHashMap(String newDirectory) { + dataBaseDirectory = newDirectory; + tables = new HashMap<>(); + } + + @Override + public Table getTable(String name) throws IllegalArgumentException { + if (name == null) { + throw new IllegalArgumentException("null argument"); + } + if (tables.containsKey(name)) { + return tables.get(name); + } else { + return null; + } + } + + @Override + public Table createTable(String name, List> columnTypes) throws IOException, IllegalArgumentException { + if (name == null || columnTypes == null) { + throw new IllegalArgumentException("null argument"); + } + TypesUtils.checkTypes(columnTypes); + if (tables.containsKey(name)) { + return null; + } else { + Path pathOfNewTable = Paths.get(dataBaseDirectory, name); + Path pathOfNewTableSignatureFile = Paths.get(dataBaseDirectory, name, "signature.tsv"); + if (Files.exists(pathOfNewTable) & Files.isDirectory(pathOfNewTable)) { + throw new IllegalArgumentException("this directory already exists"); + } + try { + Files.createDirectory(pathOfNewTable); + Files.createFile(pathOfNewTableSignatureFile); + try (FileWriter fileOut = new FileWriter(pathOfNewTableSignatureFile.toString())) { + fileOut.write(TypesUtils.toFileSignature(columnTypes)); + } + FileMap newTable = new FileMap(pathOfNewTable.toString(), columnTypes, this); + tables.put(name, newTable); + return newTable; + } catch (IOException e) { + throw new IOException(); + } + } + } + + @Override + public void removeTable(String name) throws IllegalArgumentException, IllegalStateException, IOException { + if (name == null) { + throw new IllegalArgumentException("null argument"); + } + if (tables.containsKey(name)) { + Path pathForRemoveTable = Paths.get(dataBaseDirectory, name); + tables.remove(name); + currentTable = null; + FileUtils.rmdir(pathForRemoveTable); + } else { + throw new IllegalStateException("table \'" + name + "\' doesn't exist"); + } + } + + @Override + public Storeable createFor(Table table) { + Object[] startValues = new Object[table.getColumnsCount()]; + return new AbstractStoreable(startValues, table); + } + + @Override + public Storeable createFor(Table table, List values) throws ColumnFormatException, IndexOutOfBoundsException { + if (table.getColumnsCount() != values.size()) { + throw new IndexOutOfBoundsException("number of types"); + } + List objValues = new ArrayList<>(values); + List> typeList = new ArrayList<>(); + for (int i = 0; i < table.getColumnsCount(); ++i) { + if (objValues.get(i).getClass() != (table.getColumnType(i))) { + throw new ColumnFormatException("mismatch column type"); + } + typeList.add(table.getColumnType(i)); + } + TypesUtils.checkNewStorableValue(typeList, objValues); + return new AbstractStoreable(objValues.toArray(), table); + } + + @Override + public String serialize(Table table, Storeable value) throws ColumnFormatException { + if (table.getColumnsCount() != TypesUtils.getSizeOfStoreable(value)) { + throw new ColumnFormatException("wrong size"); + } + for (int i = 0; i < table.getColumnsCount(); ++i) { + if (!table.getColumnType(i).equals(value.getColumnAt(i).getClass())) { + throw new ColumnFormatException("need: " + table.getColumnType(i) + + ", but got:" + value.getColumnAt(i).getClass()); + } + } + return Serializator.serialize(table, value); + } + + @Override + public Storeable deserialize(Table table, String value) throws ParseException { + return Serializator.deserialize(table, value); + } + + @Override + public List getTableNames() { + List result = new ArrayList<>(); + Collection filemaps = tables.values(); + for (FileMap oneTable : filemaps) { + result.add(oneTable.getName()); + } + return result; + } + + public Map getTables() { + return tables; + } + + public void setCurrentTable(FileMap newCurrentTable) { + currentTable = newCurrentTable; + } + + public FileMap getCurrentTable() { + return currentTable; + } + + public boolean init() throws BadFileException { + String[] listOfFiles = new File(dataBaseDirectory).list(); + for (String oneFile: listOfFiles) { + Path oneTablePath = Paths.get(dataBaseDirectory, oneFile); + Path oneTableSignaturePath = Paths.get(dataBaseDirectory, oneFile, "signature.tsv"); + if (Files.isDirectory(oneTablePath) & Files.exists(oneTableSignaturePath)) { + try (Scanner input = new Scanner(oneTableSignaturePath)) { + String[] types; + if (input.hasNext()) { + types = input.nextLine().trim().split("\\s+"); + List> newTypeList = TypesUtils.toTypeList(types); + if (newTypeList != null) { + tables.put(oneFile, new FileMap(oneTablePath.toString(), newTypeList, this)); + } + } + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } + } + } + boolean allRight = true; + Set> pairSet = tables.entrySet(); + for (Entry oneFileMap: pairSet) { + if (!oneFileMap.getValue().init()) { + allRight = false; + } + } + return allRight; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/MFileHashMapFactory.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MFileHashMapFactory.java similarity index 61% rename from src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/MFileHashMapFactory.java rename to src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MFileHashMapFactory.java index 349f418de..b60a251f9 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/MFileHashMapFactory.java +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MFileHashMapFactory.java @@ -1,7 +1,7 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; +package ru.fizteh.fivt.students.titov.multi_file_hash_map; -import ru.fizteh.fivt.storage.strings.TableProvider; -import ru.fizteh.fivt.storage.strings.TableProviderFactory; +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; import java.io.IOException; import java.nio.file.Files; @@ -11,7 +11,7 @@ public class MFileHashMapFactory implements TableProviderFactory { public MFileHashMapFactory() {} - public TableProvider create(String dir) throws IllegalArgumentException { + public TableProvider create(String dir) throws IOException { if (dir == null) { throw new IllegalArgumentException(); } @@ -23,16 +23,12 @@ public TableProvider create(String dir) throws IllegalArgumentException { throw new IllegalArgumentException(); } } else { - try { - Files.createDirectory(dataBaseDirectory); - } catch (IOException e) { - throw new IllegalArgumentException(); - } + Files.createDirectory(dataBaseDirectory); } MFileHashMap myMFileHashMap = new MFileHashMap(dataBaseDirectory.toString()); if (!myMFileHashMap.init()) { - throw new IllegalArgumentException(); + throw new IOException("error while initialization"); } return myMFileHashMap; } diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/Main.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/Main.java similarity index 57% rename from src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/Main.java rename to src/ru/fizteh/fivt/students/titov/multi_file_hash_map/Main.java index a6d71eb11..5cce857de 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/MultiFileHashMapPackage/Main.java +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/Main.java @@ -1,6 +1,7 @@ -package ru.fizteh.fivt.students.titov.JUnit.MultiFileHashMapPackage; +package ru.fizteh.fivt.students.titov.multi_file_hash_map; -import ru.fizteh.fivt.students.titov.JUnit.FileMapPackage.Shell; +import ru.fizteh.fivt.students.titov.file_map.BadFileException; +import ru.fizteh.fivt.students.titov.file_map.Shell; import java.io.IOException; import java.nio.file.Files; @@ -8,14 +9,16 @@ import java.nio.file.Paths; public class Main { - public static void main(String[] args) { + private static final String PROJECTPROPERTY = "fizteh.db.dir"; - if (System.getProperty("fizteh.db.dir") == null) { - System.out.println("we need working directory"); + public static void main(String[] args) throws BadFileException { + + if (System.getProperty(PROJECTPROPERTY) == null) { + System.err.println("we need working directory"); System.exit(6); } Path dataBaseDirectory - = Paths.get(System.getProperty("user.dir")).resolve(System.getProperty("fizteh.db.dir")); + = Paths.get(System.getProperty("user.dir")).resolve(System.getProperty(PROJECTPROPERTY)); boolean allRight = true; if (Files.exists(dataBaseDirectory)) { @@ -58,17 +61,17 @@ public static void main(String[] args) { public static void setUpShell(Shell myShell) { - myShell.addCommand(new CommandCreate()); - myShell.addCommand(new CommandDrop()); - myShell.addCommand(new CommandUse()); - myShell.addCommand(new CommandGetDistribute()); - myShell.addCommand(new CommandPutDistribute()); - myShell.addCommand(new CommandListDistribute()); - myShell.addCommand(new CommandRemoveDistribute()); - myShell.addCommand(new CommandShowTables()); - myShell.addCommand(new CommandRollback()); - myShell.addCommand(new CommandCommit()); - myShell.addCommand(new CommandSize()); + myShell.addCommand(new CreateCommand()); + myShell.addCommand(new DropCommand()); + myShell.addCommand(new UseCommand()); + myShell.addCommand(new GetDistributeCommand()); + myShell.addCommand(new PutDistributeCommand()); + myShell.addCommand(new ListDistributeCommand()); + myShell.addCommand(new RemoveDistributeCommand()); + myShell.addCommand(new ShowTablesCommand()); + myShell.addCommand(new RollbackCommand()); + myShell.addCommand(new CommitCommand()); + myShell.addCommand(new SizeCommand()); + myShell.addCommand(new ExitCommand()); } } - diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MultiFileHashMapCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MultiFileHashMapCommand.java new file mode 100644 index 000000000..32011023d --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/MultiFileHashMapCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.Command; +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +public abstract class MultiFileHashMapCommand extends Command { + + public void initialize(String commandName, int n) { + name = commandName; + numberOfArguments = n; + } + + public boolean isTable(FileMap currentTable) { + if (currentTable == null) { + System.out.println("no table"); + return true; + } + return false; + } +} + diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/PutDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/PutDistributeCommand.java new file mode 100644 index 000000000..805c57667 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/PutDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; +import ru.fizteh.fivt.students.titov.file_map.PutFileMapCommand; + +public class PutDistributeCommand extends MultiFileHashMapCommand { + public PutDistributeCommand() { + initialize("put", -1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + PutFileMapCommand commandPut = new PutFileMapCommand(); + return commandPut.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/RemoveDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/RemoveDistributeCommand.java new file mode 100644 index 000000000..b6ebab15c --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/RemoveDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; +import ru.fizteh.fivt.students.titov.file_map.RemoveFileMapCommand; + +public class RemoveDistributeCommand extends MultiFileHashMapCommand { + public RemoveDistributeCommand() { + initialize("remove", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + RemoveFileMapCommand removeCommand = new RemoveFileMapCommand(); + return removeCommand.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/RollbackCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/RollbackCommand.java new file mode 100644 index 000000000..586b11166 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/RollbackCommand.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +public class RollbackCommand extends MultiFileHashMapCommand { + public RollbackCommand() { + initialize("rollback", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + isTable(currentTable); + } else { + System.out.println(currentTable.rollback()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ShowTablesCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ShowTablesCommand.java new file mode 100644 index 000000000..dc4c74a81 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/ShowTablesCommand.java @@ -0,0 +1,25 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +import java.util.Map.Entry; +import java.util.Set; + +public class ShowTablesCommand extends MultiFileHashMapCommand { + public ShowTablesCommand() { + initialize("show", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + if (!args[1].equals("tables")) { + System.err.println(name + ": wrong arguments"); + return false; + } + Set> pairSet = myMap.getTables().entrySet(); + for (Entry oneTable: pairSet) { + System.out.println(oneTable.getKey() + " " + oneTable.getValue().size()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/SizeCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/SizeCommand.java new file mode 100644 index 000000000..7c0a7ef86 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/SizeCommand.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +public class SizeCommand extends MultiFileHashMapCommand { + public SizeCommand() { + initialize("size", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + isTable(currentTable); + } else { + System.out.println(currentTable.size()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/UseCommand.java b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/UseCommand.java new file mode 100644 index 000000000..84518beb2 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/multi_file_hash_map/UseCommand.java @@ -0,0 +1,30 @@ +package ru.fizteh.fivt.students.titov.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +public class UseCommand extends MultiFileHashMapCommand { + private static final String USING = "using "; + public UseCommand() { + initialize("use", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap newCurrentTable = (FileMap) myMap.getTable(args[1]); + if (newCurrentTable != null) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + myMap.setCurrentTable(newCurrentTable); + System.out.println(USING + args[1]); + } else if (currentTable.getNumberOfUncommittedChanges() > 0) { + System.out.println(currentTable.getNumberOfUncommittedChanges() + " unsaved changes"); + } else { + myMap.setCurrentTable(newCurrentTable); + System.out.println(USING + args[1]); + } + } else { + System.out.println(args[1] + " not exists"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/BadFileException.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/BadFileException.java new file mode 100644 index 000000000..33a121eb7 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/BadFileException.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +import java.io.IOException; + +public class BadFileException extends IOException { + public BadFileException(Throwable cause) { + super(cause); + } + + public BadFileException() { + super("Can't read from disk"); + } + + @Override + public String getMessage() { + Throwable cause = getCause(); + return cause.getClass().getName() + ": " + cause.getMessage(); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/Command.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/Command.java new file mode 100644 index 000000000..9f352831d --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/Command.java @@ -0,0 +1,13 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +public abstract class Command { + protected String name; + protected int numberOfArguments; + + public abstract boolean run(T object, String[] args); + + @Override + public final String toString() { + return name; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/FileMap.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/FileMap.java new file mode 100644 index 000000000..c6e93fe34 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/FileMap.java @@ -0,0 +1,456 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.students.titov.parallel.storeable.TypesUtils; +import ru.fizteh.fivt.students.titov.parallel.storeable.Serializator; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.MapMode; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.ParseException; +import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class FileMap implements Table { + private static final int MAX_NUMBER_OF_DIRS = 16; + private static final int MAX_NUMBER_OF_FILES = 16; + private static final String SUFFIX_OF_DIRECTORY = ".dir"; + private static final String SUFFIX_OF_FILE = ".dat"; + private static final String FILE_ENCODING = "UTF-8"; + private Map stableData; + private List> typeList; + private int numberOfColumns; + private String directoryOfTable; + private TableProvider parent; + private Lock lockForCommit; + private ThreadLocal diff; + + private class Difference { + private HashMap addedData; + private HashMap changedData; + private HashSet removedData; + + Difference() { + addedData = new HashMap<>(); + changedData = new HashMap<>(); + removedData = new HashSet<>(); + } + } + + private int getNumberOfDirectory(int hash) { + int result = hash % MAX_NUMBER_OF_DIRS; + if (result < 0) { + result += MAX_NUMBER_OF_DIRS; + } + return result; + } + + private int getNumberOfFile(int hash) { + int result = hash / MAX_NUMBER_OF_DIRS % MAX_NUMBER_OF_FILES; + if (result < 0) { + result += MAX_NUMBER_OF_FILES; + } + return result; + } + + private void clearAll() { + Difference innerDiff = diff.get(); + innerDiff.removedData.clear(); + innerDiff.addedData.clear(); + innerDiff.changedData.clear(); + } + + /** + * Create empty Filemap + * + * @param newDirectory - directory of this file_map + * @param newTypeList - list of types (signature of table) + */ + public FileMap(String newDirectory, List> newTypeList, TableProvider newParent) throws IOException { + directoryOfTable = newDirectory; + stableData = new HashMap<>(); + typeList = newTypeList; + numberOfColumns = typeList.size(); + parent = newParent; + lockForCommit = new ReentrantLock(); + diff = ThreadLocal.withInitial(()->new Difference()); + if (!init()) { + throw new IOException("error while initialization"); + } + } + + + public TableProvider getTableProvider() { + return parent; + } + + @Override + public String getName() { + return Paths.get(directoryOfTable).getFileName().toString(); + } + + @Override + public Storeable get(String key) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("null argument"); + } + Difference innerDiff = diff.get(); + if (innerDiff.removedData.contains(key)) { + return null; + } + if (innerDiff.changedData.containsKey(key)) { + return innerDiff.changedData.get(key); + } + if (innerDiff.addedData.containsKey(key)) { + return innerDiff.addedData.get(key); + } + return stableData.get(key); + } + + @Override + public Storeable remove(String key) throws IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException("null argument"); + } + Difference innerDiff = diff.get(); + if (innerDiff.removedData.contains(key)) { + return null; + } + if (innerDiff.addedData.containsKey(key)) { + return innerDiff.addedData.remove(key); + } + if (innerDiff.changedData.containsKey(key)) { + innerDiff.removedData.add(key); + return innerDiff.changedData.remove(key); + } + if (stableData.containsKey(key)) { + innerDiff.removedData.add(key); + } + return stableData.get(key); + } + + @Override + public Storeable put(String key, Storeable value) throws IllegalArgumentException { + if (key == null || value == null) { + throw new IllegalArgumentException("null argument"); + } + TypesUtils.checkNewStorableValue(typeList, value); + boolean wasDeleted = false; + Difference innerDiff = diff.get(); + if (innerDiff.removedData.contains(key)) { + innerDiff.removedData.remove(key); + wasDeleted = true; + } + if (innerDiff.changedData.containsKey(key)) { + return innerDiff.changedData.put(key, value); + } + if (innerDiff.addedData.containsKey(key)) { + return innerDiff.addedData.put(key, value); + } + + if (stableData.containsKey(key)) { + innerDiff.changedData.put(key, value); + } else { + innerDiff.addedData.put(key, value); + } + + if (wasDeleted) { + return null; + } else { + return stableData.get(key); + } + } + + @Override + public int size() { + Difference innerDiff = diff.get(); + return stableData.size() + innerDiff.addedData.size() - innerDiff.removedData.size(); + } + + @Override + public int getColumnsCount() { + return numberOfColumns; + } + + @Override + public Class getColumnType(int columnIndex) throws IndexOutOfBoundsException { + return typeList.get(columnIndex); + } + + @Override + public int rollback() { + Difference innerDiff = diff.get(); + int result = innerDiff.changedData.size() + innerDiff.removedData.size() + innerDiff.addedData.size(); + clearAll(); + return result; + } + + @Override + public int commit() throws IOException { + try { + lockForCommit.lock(); + + Difference innerDiff = diff.get(); + HashMap tmpAddedData = new HashMap<>(innerDiff.addedData); + HashMap tmpBufferAdded = new HashMap<>(innerDiff.addedData); + HashMap tmpChangedData = new HashMap<>(innerDiff.changedData); + HashMap tmpBufferChanged = new HashMap<>(innerDiff.changedData); + + tmpAddedData.keySet().removeAll(stableData.keySet()); + tmpBufferChanged.keySet().removeAll(stableData.keySet()); + tmpAddedData.putAll(tmpBufferChanged); + + tmpChangedData.keySet().retainAll(stableData.keySet()); + tmpBufferAdded.keySet().retainAll(stableData.keySet()); + tmpChangedData.putAll(tmpBufferAdded); + + innerDiff.removedData.retainAll(stableData.keySet()); + int result = tmpChangedData.size() + + innerDiff.removedData.size() + tmpAddedData.size(); + stableData.keySet().removeAll(innerDiff.removedData); + stableData.putAll(tmpChangedData); + stableData.putAll(tmpAddedData); + + boolean allRight = true; + if (tmpChangedData.size() + innerDiff.removedData.size() > 0) { + Set reloadKeys = innerDiff.removedData; + reloadKeys.addAll(tmpChangedData.keySet()); + for (String oneKey : reloadKeys) { + if (!save(oneKey, false)) { + allRight = false; + } + } + } + for (String oneKey : tmpAddedData.keySet()) { + if (!save(oneKey, true)) { + allRight = false; + } + } + if (allRight) { + return result; + } else { + throw new IOException(); + } + } finally { + lockForCommit.unlock(); + clearAll(); + } + } + + public List list() { + Difference innerDiff = diff.get(); + ArrayList keyList = new ArrayList<>(stableData.keySet()); + keyList.removeAll(innerDiff.removedData); + keyList.addAll(innerDiff.addedData.keySet()); + return keyList; + } + + @Override + public int getNumberOfUncommittedChanges() { + Difference innerDiff = diff.get(); + return innerDiff.addedData.size() + innerDiff.changedData.size() + innerDiff.removedData.size(); + } + + public boolean init() throws BadFileException { + String[] listOfDirectories = new File(directoryOfTable).list(); + if (listOfDirectories == null) { + return true; + } + for (String directory: listOfDirectories) { + String currentDirectory = directoryOfTable + File.separator + + directory; + if (!Files.isDirectory(Paths.get(currentDirectory))) { + continue; + } + String[] listOfFiles = new File(currentDirectory).list(); + for (String oneFile : listOfFiles) { + String currentFile = currentDirectory + File.separator + + oneFile; + int numberOfDirectory = directory.charAt(0) - '0'; + if (directory.charAt(1) != '.') { + numberOfDirectory = 10 * numberOfDirectory + directory.charAt(1) - '0'; + } + int numberOfFile = oneFile.charAt(0) - '0'; + if (oneFile.charAt(1) != '.') { + numberOfFile = 10 * numberOfFile + oneFile.charAt(1) - '0'; + } + try (FileInputStream inStream = new FileInputStream(currentFile)) { + FileChannel inputChannel; + inputChannel = inStream.getChannel(); + ByteBuffer bufferFromDisk; + try { + bufferFromDisk = + inputChannel.map(MapMode.READ_ONLY, 0, inputChannel.size()); + } catch (IOException e) { + throw new BadFileException(e); + } + try { + while (bufferFromDisk.hasRemaining()) { + byte[] key; + byte[] value; + int keySize; + int valueSize; + if (bufferFromDisk.remaining() >= 4) { + keySize = bufferFromDisk.getInt(); + key = new byte[keySize]; + } else { + throw new BadFileException(); + } + + if (keySize < 0) { + throw new BadFileException(); + } + + if (bufferFromDisk.remaining() >= keySize) { + bufferFromDisk.get(key, 0, key.length); + } else { + throw new BadFileException(); + } + + if (bufferFromDisk.remaining() >= 4) { + valueSize = bufferFromDisk.getInt(); + if (valueSize < 0) { + throw new BadFileException(); + } + value = new byte[valueSize]; + } else { + throw new BadFileException(); + } + if (bufferFromDisk.remaining() >= valueSize) { + bufferFromDisk.get(value, 0, value.length); + } else { + throw new BadFileException(); + } + + String keyString = new String(key, FILE_ENCODING); + if (getNumberOfDirectory(keyString.hashCode()) != numberOfDirectory + || getNumberOfFile(keyString.hashCode()) != numberOfFile) { + throw new BadFileException(); + } + + try { + stableData.put(new String(key, FILE_ENCODING), + Serializator.deserialize(this, new String(value, "UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new BadFileException(e); + } catch (ParseException e) { + throw new BadFileException(e); + } + } + } catch (NullPointerException e) { + throw new BadFileException(e); + } + } catch (FileNotFoundException e) { + throw new BadFileException(e); + } catch (BadFileException e) { + throw new BadFileException(e); + } catch (IOException e) { + throw new BadFileException(e); + } + } + } + return true; + } + + /** + * Returns True if the record on the disc was successful and otherwise False. + */ + public boolean save(String key, boolean appendFile) throws BadFileException { + HashSet keySet = new HashSet<>(); + ByteBuffer bufferForSize = ByteBuffer.allocate(4); + + int numberOfDirectory = getNumberOfDirectory(key.hashCode()); + int numberOfFile = getNumberOfFile(key.hashCode()); + if (appendFile) { + keySet.clear(); + keySet.add(key); + } else { + Set keySetFromDB = stableData.keySet(); + for (String oneKey : keySetFromDB) { + if (numberOfDirectory == getNumberOfDirectory(oneKey.hashCode()) + & numberOfFile == getNumberOfFile(oneKey.hashCode())) { + keySet.add(oneKey); + } + } + } + + Path directoryForsave; + Path fileForsave; + directoryForsave = Paths.get(directoryOfTable, numberOfDirectory + SUFFIX_OF_DIRECTORY); + if (!Files.exists(directoryForsave)) { + try { + Files.createDirectory(directoryForsave); + } catch (IOException e) { + System.err.println("error while creating directory for save"); + return false; + } + } + + fileForsave = Paths.get(directoryForsave.toString(), numberOfFile + SUFFIX_OF_FILE); + if (!Files.exists(fileForsave)) { + try { + Files.createFile(fileForsave); + } catch (IOException e) { + System.err.println("error while creating file for save"); + return false; + } + } + + try (FileOutputStream outputStream + = new FileOutputStream(fileForsave.toString(), appendFile)) { + for (String oneKey : keySet) { + try { + byte[] keyByte = oneKey.getBytes("UTF-8"); + byte[] valueByte = Serializator.serialize(this, stableData.get(oneKey)).getBytes("UTF-8"); + outputStream.write(bufferForSize.putInt(0, keyByte.length).array()); + outputStream.write(keyByte); + outputStream.write(bufferForSize.putInt(0, valueByte.length).array()); + outputStream.write(valueByte); + } catch (UnsupportedEncodingException e) { + System.err.println("unsupported encoding"); + return false; + } catch (IOException e) { + System.err.println("io exception"); + return false; + } + } + } catch (FileNotFoundException e) { + System.err.println("file not found"); + return false; + } catch (IOException e) { + System.err.println("io exception"); + return false; + } + + if (!appendFile) { + deleteEmptyFiles(directoryForsave, fileForsave); + } + return true; + } + + public boolean deleteEmptyFiles(Path directory, Path file) throws BadFileException { + try { + if (Files.size(file) == 0) { + Files.delete(file); + } + } catch (IOException e) { + throw new BadFileException(e); + } + String[] listOfFiles = new File(directory.toString()).list(); + if (listOfFiles.length == 0) { + try { + Files.delete(directory); + } catch (IOException e) { + throw new BadFileException(e); + } + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/FileMapCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/FileMapCommand.java new file mode 100644 index 000000000..e0a43c9d2 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/FileMapCommand.java @@ -0,0 +1,8 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +public abstract class FileMapCommand extends Command { + public void initialize(String commandName, int n) { + name = commandName; + numberOfArguments = n; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/GetFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/GetFileMapCommand.java new file mode 100644 index 000000000..7b9fd3074 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/GetFileMapCommand.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.titov.parallel.storeable.Serializator; + +public class GetFileMapCommand extends FileMapCommand { + public GetFileMapCommand() { + initialize("get", 2); + } + @Override + public boolean run(FileMap fileMap, String[] args) { + Storeable value = fileMap.get(args[1]); + if (value != null) { + System.err.println("found\n" + Serializator.serialize(fileMap, fileMap.get(args[1]))); + } else { + System.err.println("not found"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/ListFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/ListFileMapCommand.java new file mode 100644 index 000000000..29ba0a976 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/ListFileMapCommand.java @@ -0,0 +1,16 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +import java.util.List; + +public class ListFileMapCommand extends FileMapCommand { + public ListFileMapCommand() { + initialize("list", 1); + } + + @Override + public boolean run(FileMap fileMap, String[] args) { + List allKeys = fileMap.list(); + System.out.println(String.join(", ", allKeys)); + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/PutFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/PutFileMapCommand.java new file mode 100644 index 000000000..0cd9e9150 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/PutFileMapCommand.java @@ -0,0 +1,32 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.titov.parallel.storeable.Serializator; + +import java.text.ParseException; +import java.util.NoSuchElementException; + +public class PutFileMapCommand extends FileMapCommand { + public PutFileMapCommand() { + initialize("put", 2); + } + @Override + public boolean run(FileMap fileMap, String[] args) { + Storeable oldValue = fileMap.get(args[1]); + try { + fileMap.put(args[1], Serializator.deserialize(fileMap, args[2])); + } catch (ParseException e) { + System.out.println("wrong type (" + e.getMessage() + ")"); + return false; + } catch (NoSuchElementException e) { + System.err.println("error: not xml format value"); + return false; + } + if (oldValue != null) { + System.out.println("overwrite\n" + Serializator.serialize(fileMap, oldValue)); + } else { + System.out.println("new"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/file_map/RemoveFileMapCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/RemoveFileMapCommand.java new file mode 100644 index 000000000..6fd4f910a --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/RemoveFileMapCommand.java @@ -0,0 +1,19 @@ +package ru.fizteh.fivt.students.titov.parallel.file_map; + +import ru.fizteh.fivt.storage.structured.Storeable; + +public class RemoveFileMapCommand extends FileMapCommand { + public RemoveFileMapCommand() { + initialize("remove", 2); + } + @Override + public boolean run(FileMap fileMap, String[] args) { + Storeable value = fileMap.remove(args[1]); + if (value != null) { + System.out.println("removed"); + } else { + System.out.println("not found"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/Shell.java b/src/ru/fizteh/fivt/students/titov/parallel/file_map/Shell.java similarity index 56% rename from src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/Shell.java rename to src/ru/fizteh/fivt/students/titov/parallel/file_map/Shell.java index bd3280850..b34026a14 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/Shell.java +++ b/src/ru/fizteh/fivt/students/titov/parallel/file_map/Shell.java @@ -1,22 +1,24 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; +package ru.fizteh.fivt.students.titov.parallel.file_map; import java.util.HashMap; import java.util.Scanner; -public class Shell { +public class Shell { + private static final String INVITATION = "$ "; + private HashMap> shellCommands; - private HashMap shellCommands; - - public Shell() { - shellCommands = new HashMap(); + private T objectForShell; + public Shell(T obj) { + shellCommands = new HashMap<>(); + objectForShell = obj; } - public void addCommand(final Command newCommand) { + public void addCommand(Command newCommand) { shellCommands.put(newCommand.toString(), newCommand); } public boolean interactiveMode() { - System.out.print("$ "); + System.out.print(INVITATION); boolean ended = false; boolean errorOccuried = false; @@ -31,6 +33,12 @@ public boolean interactiveMode() { } for (String oneCommand : parsedCommands) { parsedArguments = oneCommand.trim().split("\\s+"); + if (parsedArguments[0].equals("put")) { + if (oneCommand.contains("<")) { + String valueForPut = oneCommand.trim().substring(oneCommand.indexOf('<')); + parsedArguments[2] = valueForPut; + } + } if (parsedArguments.length == 0 || parsedArguments[0].equals("")) { continue; } @@ -38,18 +46,22 @@ public boolean interactiveMode() { ended = true; break; } - Command commandToExecute = shellCommands.get(parsedArguments[0]); + Command commandToExecute = shellCommands.get(parsedArguments[0]); if (commandToExecute != null) { - if (!commandToExecute.run(parsedArguments)) { + if (commandToExecute.numberOfArguments != parsedArguments.length + & commandToExecute.numberOfArguments != -1) { + System.err.println(commandToExecute.name + ": wrong number of arguments"); + errorOccuried = true; + } else if (!commandToExecute.run(objectForShell, parsedArguments)) { errorOccuried = true; } } else { - System.out.println(parsedArguments[0] + ": command not found"); + System.err.println(parsedArguments[0] + ": command not found"); errorOccuried = true; } } if (!ended) { - System.out.print("$ "); + System.out.print(INVITATION); } } } @@ -79,16 +91,21 @@ public boolean batchMode(final String[] arguments) { if (parsedArguments[0].equals("exit")) { return !errorOccuried; } - Command commandToExecute = shellCommands.get(parsedArguments[0]); + Command commandToExecute = shellCommands.get(parsedArguments[0]); if (commandToExecute != null) { - if (!commandToExecute.run(parsedArguments)) { + if (commandToExecute.numberOfArguments != parsedArguments.length + & commandToExecute.numberOfArguments != -1) { + System.err.println(commandToExecute.name + " wrong number of arguments"); + errorOccuried = true; + } else if (!commandToExecute.run(objectForShell, parsedArguments)) { errorOccuried = true; } } else { - System.out.println(parsedArguments[0] + ": command not found"); + System.err.println(parsedArguments[0] + ": command not found"); errorOccuried = true; } } return !errorOccuried; } } + diff --git a/src/ru/fizteh/fivt/students/titov/parallel/junit/TestStoreable.java b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestStoreable.java new file mode 100644 index 000000000..d3f939638 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestStoreable.java @@ -0,0 +1,109 @@ +package ru.fizteh.fivt.students.titov.parallel.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import ru.fizteh.fivt.storage.structured.*; +import ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.parallel.shell.FileUtils; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TestStoreable { + static String providerDirectory; + static String tableName; + static TableProviderFactory factory; + static TableProvider provider; + static Table table; + static Storeable entry; + static List> typeList; + + @Before + public void setUp() throws Exception { + providerDirectory = Paths.get("").resolve("provider").toString(); + tableName = "testTable2"; + factory = new MFileHashMapFactory(); + typeList = new ArrayList<>(); + typeList.add(Integer.class); + typeList.add(String.class); + try { + provider = factory.create(providerDirectory); + table = provider.createTable(tableName, typeList); + entry = provider.createFor(table); + } catch (IOException e) { + //suppress + } + } + + @After + public void tearDown() throws Exception { + try { + FileUtils.rmdir(Paths.get(providerDirectory)); + } catch (IOException e) { + //suppress + } + FileUtils.mkdir(Paths.get(providerDirectory)); + } + + @Test + public void testSetColumnAt() throws Exception { + entry.setColumnAt(0, null); + boolean exceptionWas = false; + try { + entry.setColumnAt(0, "new"); + } catch (ColumnFormatException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + exceptionWas = false; + try { + entry.setColumnAt(2, "new"); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } + + @Test + public void testGetColumnAt() throws Exception { + entry.setColumnAt(0, 1); + assertEquals((entry.getColumnAt(0)), 1); + + boolean exceptionWas = false; + try { + entry.getColumnAt(2); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } + + @Test + public void testGetIntAt() throws Exception { + entry.setColumnAt(0, 1); + entry.setColumnAt(1, "new"); + assertTrue(entry.getIntAt(0) == 1); + + boolean exceptionWas = false; + try { + entry.getIntAt(1); + } catch (ColumnFormatException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + + exceptionWas = false; + try { + entry.getIntAt(100); + } catch (IndexOutOfBoundsException e) { + exceptionWas = true; + } + assertTrue(exceptionWas); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTable.java b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTable.java new file mode 100644 index 000000000..acddcc7f1 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTable.java @@ -0,0 +1,257 @@ +package ru.fizteh.fivt.students.titov.parallel.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import ru.fizteh.fivt.storage.structured.*; +import ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class TestTable { + String key; + Storeable value; + Storeable newValue; + String providerDirectory; + String tableName; + String newTableName; + + Table testTable; + Table newTestTable; + TableProvider provider; + TableProviderFactory factory; + + static List> typeList; + static List> newTypeList; + + + @BeforeClass + public static void setUpBeforeClass() { + typeList = new ArrayList<>(); + typeList.add(Integer.class); + typeList.add(String.class); + typeList.add(Boolean.class); + + newTypeList = new ArrayList<>(); + newTypeList.add(Double.class); + newTypeList.add(Byte.class); + newTypeList.add(Float.class); + } + + @Before + public void setUp() { + key = "key"; + providerDirectory = Paths.get("").resolve("provider").toString(); + tableName = "testTable"; + newTableName = "newTestTable"; + factory = new MFileHashMapFactory(); + try { + provider = factory.create(providerDirectory); + testTable = provider.createTable(tableName, typeList); + newTestTable = provider.createTable(newTableName, newTypeList); + } catch (IOException e) { + //suppress + } + value = provider.createFor(testTable); + newValue = provider.createFor(testTable); + + value.setColumnAt(0, 100); + value.setColumnAt(1, "qwerty"); + value.setColumnAt(2, true); + + newValue.setColumnAt(0, 585); + newValue.setColumnAt(1, "newQwerty"); + newValue.setColumnAt(2, false); + } + + @After + public void tearDown() { + try { + provider.removeTable(tableName); + provider.removeTable(newTableName); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testGetName() throws Exception { + assertEquals(testTable.getName(), tableName); + } + + @Test + public void testGet() throws Exception { + assertNull(testTable.get(key)); + testTable.put(key, value); + assertEquals(testTable.get(key), value); + testTable.put(key, newValue); + assertEquals(testTable.get(key), newValue); + testTable.remove(key); + assertNull(testTable.get(key)); + testTable.rollback(); + + testTable.put(key, value); + testTable.commit(); + testTable.put(key, newValue); + assertEquals(testTable.get(key), newValue); + testTable.remove(key); + assertNull(testTable.get(key)); + } + + @Test + public void testRemove() throws Exception { + assertNull(testTable.remove(key)); + testTable.put(key, value); + assertEquals(testTable.remove(key), value); + + testTable.rollback(); + testTable.put(key, value); + assertEquals(testTable.remove(key), value); + testTable.put(key, value); + testTable.commit(); + assertEquals(testTable.remove(key), value); + assertNull(testTable.remove(key)); + } + + @Test + public void testPutCorrectValue() throws Exception { + assertNull(testTable.put(key, value)); + assertEquals(testTable.put(key, value), value); + assertEquals(testTable.get(key), value); + assertEquals(testTable.put(key, newValue), value); + assertEquals(testTable.get(key), newValue); + testTable.remove(key); + assertNull(testTable.put(key, value)); + + String keyForCommit = "keyCM"; + Storeable valueForCommit = ((FileMap) testTable).getTableProvider().createFor(testTable); + valueForCommit.setColumnAt(0, 999); + valueForCommit.setColumnAt(1, "commit-value"); + valueForCommit.setColumnAt(2, false); + + int size = 5; + for (int i = 0; i < size; ++i) { + valueForCommit.setColumnAt(0, 999 + i); + assertNull(testTable.put(keyForCommit + i, valueForCommit)); + } + testTable.commit(); + for (int i = 0; i < size; ++i) { + valueForCommit.setColumnAt(0, 999 + i); + assertEquals(testTable.get(keyForCommit + i), valueForCommit); + } + + Storeable freshValue = ((FileMap) testTable).getTableProvider().createFor(testTable); + freshValue.setColumnAt(0, 123456); + freshValue.setColumnAt(1, "FRESH!!!"); + freshValue.setColumnAt(2, true); + + testTable.rollback(); + testTable.remove(keyForCommit + 1); + + valueForCommit.setColumnAt(0, 1000); + assertNull(testTable.put(keyForCommit + 1, valueForCommit)); + valueForCommit.setColumnAt(0, 1001); + assertEquals(testTable.put(keyForCommit + 2, freshValue), valueForCommit); + + Storeable changedFreshValue = freshValue; + changedFreshValue.setColumnAt(1, "CHANGED"); + assertEquals(testTable.put(keyForCommit + 2, changedFreshValue), freshValue); + } + + @Test + public void testSize() throws Exception { + int size = 5; + for (int i = 0; i < size; ++i) { + value.setColumnAt(0, i); + testTable.put(key + i, value); + } + assertEquals(testTable.size(), size); + testTable.remove(key + 0); + assertEquals(testTable.size(), size - 1); + } + + @Test + public void testRollback() throws Exception { + int size = 5; + for (int i = 0; i < size; ++i) { + value.setColumnAt(0, i); + testTable.put(key + i, value); + } + testTable.remove(key + 0); + testTable.remove(key + 2); + testTable.put(key + 1, newValue); + assertEquals(testTable.rollback(), size - 2); + testTable.put(key, value); + assertEquals(testTable.rollback(), 1); + testTable.put(key, value); + testTable.commit(); + assertEquals(testTable.rollback(), 0); + } + + @Test + public void testCommit() throws Exception { + int size = 5; + for (int i = 0; i < size; ++i) { + value.setColumnAt(0, i); + testTable.put(key + i, value); + } + testTable.remove(key + 0); + testTable.remove(key + 2); + testTable.put(key + 1, newValue); + assertEquals(testTable.commit(), size - 2); + assertEquals(testTable.rollback(), 0); + testTable.put(key, newValue); + testTable.remove(key); + assertEquals(testTable.commit(), 0); + newValue.setColumnAt(0, 111111); + testTable.put(key + 1, newValue); + assertEquals(testTable.commit(), 1); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetNullInput() { + testTable.get(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testPutNullInput() { + testTable.put(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void testRemoveNullInput() { + testTable.remove(null); + } + + @Test(expected = ColumnFormatException.class) + public void testPutIllegalColumn() { + Storeable newValueForCheck = provider.createFor(newTestTable); + newValueForCheck.setColumnAt(0, 4.4); + newValueForCheck.setColumnAt(1, (byte) 0); + newValueForCheck.setColumnAt(2, (float) 8.8); + testTable.put("simpleKey", newValueForCheck); + } + + @Test + public void testGetColumnsCount() { + assertEquals(testTable.getColumnsCount(), 3); + } + + @Test + public void testGetColumnType() { + assertEquals(testTable.getColumnType(0), Integer.class); + try { + testTable.getColumnType(9); + fail(); + } catch (IndexOutOfBoundsException e) { + //allright + } + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTableProvider.java b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTableProvider.java new file mode 100644 index 000000000..ef36b02a1 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTableProvider.java @@ -0,0 +1,235 @@ +package ru.fizteh.fivt.students.titov.parallel.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import ru.fizteh.fivt.storage.structured.*; +import ru.fizteh.fivt.students.titov.parallel.storeable.TypesUtils; +import ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.parallel.shell.FileUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class TestTableProvider { + String providerDirectory; + String tableName; + TableProvider provider; + TableProviderFactory factory; + + static List> typeList; + static List> wrongTypeList; + + @BeforeClass + public static void setUpBeforeClass() { + typeList = new ArrayList<>(); + typeList.add(Integer.class); + typeList.add(String.class); + + wrongTypeList = new ArrayList<>(); + wrongTypeList.add(Integer.class); + wrongTypeList.add(String.class); + wrongTypeList.add(Double.class); + } + + @Before + public void setUp() { + providerDirectory = Paths.get("").resolve("provider").toString(); + tableName = "testTable"; + factory = new MFileHashMapFactory(); + try { + provider = factory.create(providerDirectory); + } catch (IOException e) { + //suppress + } + } + + @After + public void tearDown() { + try { + FileUtils.rmdir(Paths.get(providerDirectory)); + } catch (IOException e) { + //suppress + } + FileUtils.mkdir(Paths.get(providerDirectory)); + } + + @Test + public void testGetTable() throws Exception { + assertNull(provider.getTable(tableName)); + assertNotNull(provider.createTable(tableName, typeList)); + assertNotNull(provider.getTable(tableName)); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetTableNull() throws Exception { + provider.getTable(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTableDirExists() throws Exception { + FileUtils.mkdir(Paths.get(providerDirectory, tableName)); + provider.createTable(tableName, typeList); + } + + @Test + public void testCreateDouble() throws Exception { + provider.createTable(tableName, typeList); + assertNull(provider.createTable(tableName, typeList)); + } + + @Test + public void testCreateTableDirNotExists() throws Exception { + try { + FileUtils.rmdir(Paths.get(providerDirectory, tableName)); + } catch (IllegalArgumentException e) { + //suppress - means directory doesn't exist + } + assertNotNull(provider.createTable(tableName, typeList)); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTableNullDirectory() throws Exception { + provider.createTable(null, typeList); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateTableNullTypeList() throws Exception { + provider.createTable(tableName, null); + } + + @Test + public void testRemoveTableExists() throws Exception { + provider.createTable(tableName, typeList); + provider.removeTable(tableName); + assertNull(provider.getTable(tableName)); + assertTrue(!Files.exists(Paths.get(providerDirectory, tableName))); + } + + @Test(expected = IllegalStateException.class) + public void testRemoveTableNotExists() throws Exception { + provider.removeTable(tableName); + } + + @Test(expected = IllegalArgumentException.class) + public void testRemoveTableNull() throws Exception { + provider.removeTable(null); + } + + @Test + public void testSerialize() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + Storeable value = provider.createFor(newTable); + value.setColumnAt(0, 100); + value.setColumnAt(1, "example"); + + String serValue = "100example"; + assertEquals(provider.serialize(newTable, value), serValue); + + Table wrongTable; + wrongTable = provider.createTable(tableName + 2, wrongTypeList); + Storeable wrongValue = provider.createFor(wrongTable); + wrongValue.setColumnAt(0, 100); + wrongValue.setColumnAt(1, "example"); + wrongValue.setColumnAt(2, 5.5); + + try { + provider.serialize(newTable, wrongValue); + fail(); + } catch (ColumnFormatException e) { + //all right + } + } catch (IOException e) { + //suppress + } + } + + @Test + public void testDeserialize() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + String stringForParse = "100example"; + String stringForParse2 = "qwertyexample"; + try { + Storeable deserValue = provider.deserialize(newTable, stringForParse); + assertTrue(deserValue.getIntAt(0).equals(100)); + assertEquals(deserValue.getStringAt(1), "example"); + } catch (ParseException e) { + assertNotNull(null); + } + + try { + provider.deserialize(newTable, stringForParse + 2); + fail(); + } catch (ParseException e) { + //all right + } + + try { + provider.deserialize(newTable, stringForParse2); + fail(); + } catch (ParseException e) { + //all right + } + } catch (IOException e) { + //suppress + } + } + + @Test + public void testCreateFor() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + Storeable temp = provider.createFor(newTable); + assertEquals(TypesUtils.getSizeOfStoreable(temp), newTable.getColumnsCount()); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testCreateForWithValue() { + try { + Table newTable; + newTable = provider.createTable(tableName, typeList); + List value = new ArrayList<>(); + value.add(100); + value.add("new"); + Storeable temp = provider.createFor(newTable, value); + assertEquals(TypesUtils.getSizeOfStoreable(temp), newTable.getColumnsCount()); + + try { + value = new ArrayList<>(); + value.add("new"); + value.add(100); + provider.createFor(newTable, value); + fail(); + } catch (ColumnFormatException e) { + //all right + } + + try { + value = new ArrayList<>(); + value.add("new2"); + provider.createFor(newTable, value); + fail(); + } catch (IndexOutOfBoundsException e) { + //all right + } + + } catch (IOException e) { + //suppress + } + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTableProviderFactory.java b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTableProviderFactory.java new file mode 100644 index 000000000..241987fd0 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/junit/TestTableProviderFactory.java @@ -0,0 +1,56 @@ +package ru.fizteh.fivt.students.titov.parallel.junit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; +import ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map.MFileHashMapFactory; +import ru.fizteh.fivt.students.titov.parallel.shell.FileUtils; + +import java.io.IOException; +import java.nio.file.Paths; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class TestTableProviderFactory { + String dir; + TableProviderFactory testFactory; + + @Before + public void setUp() { + dir = Paths.get("").resolve("factory").toString(); + testFactory = new MFileHashMapFactory(); + } + + @After + public void tearDown() { + try { + FileUtils.rmdir(Paths.get(dir)); + FileUtils.mkdir(Paths.get(dir)); + } catch (IOException e) { + //suppress + } + } + + @Test + public void testCreateDirExists() throws Exception { + FileUtils.mkdir(Paths.get(dir)); + try { + assertNotNull(testFactory.create(dir)); + } catch (IOException e) { + assertTrue(false); + } + } + + + @Test + public void testCreateDirNotExists() throws Exception { + assertNotNull(testFactory.create(dir)); + } + + @Test (expected = IllegalArgumentException.class) + public void testCreateNull() throws Exception { + testFactory.create(null); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/CommitCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/CommitCommand.java new file mode 100644 index 000000000..2cc67cd74 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/CommitCommand.java @@ -0,0 +1,27 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +import java.io.IOException; + +public class CommitCommand extends MultiFileHashMapCommand { + public CommitCommand() { + initialize("commit", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + isTable(currentTable); + } else { + try { + System.out.println(currentTable.commit()); + } catch (IOException e) { + System.err.println("io exception while writing in file"); + return false; + } + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/CreateCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/CreateCommand.java new file mode 100644 index 000000000..cf50e7452 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/CreateCommand.java @@ -0,0 +1,51 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.students.titov.parallel.storeable.TypesUtils; + +import java.io.IOException; +import java.util.List; + +public class CreateCommand extends MultiFileHashMapCommand { + public CreateCommand() { + initialize("create", -1); + } + + @Override + public boolean run(MFileHashMap myMultiDataBase, String[] args) { + StringBuilder simpleBuilder = new StringBuilder(); + for (int i = 2; i < args.length; ++i) { + if (i != 2) { + simpleBuilder.append(" "); + } + simpleBuilder.append(args[i]); + } + String concatArgs = simpleBuilder.toString(); + if (concatArgs.lastIndexOf("(") != 0 + || concatArgs.indexOf(")") != concatArgs.length() - 1) { + System.out.println("types should be in format: \" (type1 type2 ... typeN)\""); + return false; + } + + concatArgs = new String(concatArgs.toCharArray(), 1, concatArgs.length() - 2); + List> types; + try { + types = TypesUtils.toTypeList(concatArgs.split("\\s+")); + } catch (ColumnFormatException e) { + System.err.println(e.getMessage()); + return false; + } + try { + if (myMultiDataBase.createTable(args[1], types) != null) { + System.out.println("created"); + } else { + System.out.println("\'" + args[1] + "\' already exists"); + } + } catch (IOException e) { + return false; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/DropCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/DropCommand.java new file mode 100644 index 000000000..cd72398b2 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/DropCommand.java @@ -0,0 +1,25 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import java.io.IOException; + +public class DropCommand extends MultiFileHashMapCommand { + public DropCommand() { + initialize("drop", 2); + } + + @Override + public boolean run(MFileHashMap myDataBase, String[] args) { + try { + myDataBase.removeTable(args[1]); + System.out.println("dropped"); + } catch (IOException e) { + System.err.println("io exception while removing directory"); + return false; + } catch (IllegalArgumentException e) { + System.err.println(e.getMessage()); + } catch (IllegalStateException e) { + System.err.println(e.getMessage()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ExitCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ExitCommand.java new file mode 100644 index 000000000..57b6a3079 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ExitCommand.java @@ -0,0 +1,13 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +public class ExitCommand extends MultiFileHashMapCommand { + public ExitCommand() { + initialize("exit", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + System.exit(0); + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/GetDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/GetDistributeCommand.java new file mode 100644 index 000000000..74cef2183 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/GetDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; +import ru.fizteh.fivt.students.titov.parallel.file_map.GetFileMapCommand; + +public class GetDistributeCommand extends MultiFileHashMapCommand { + public GetDistributeCommand() { + initialize("get", 2); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + GetFileMapCommand commandGet = new GetFileMapCommand(); + return commandGet.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ListDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ListDistributeCommand.java new file mode 100644 index 000000000..191f81bde --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ListDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; +import ru.fizteh.fivt.students.titov.parallel.file_map.ListFileMapCommand; + +public class ListDistributeCommand extends MultiFileHashMapCommand { + public ListDistributeCommand() { + initialize("list", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + ListFileMapCommand commandList = new ListFileMapCommand(); + return commandList.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MFileHashMap.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MFileHashMap.java new file mode 100644 index 000000000..013f564c4 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MFileHashMap.java @@ -0,0 +1,206 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.ParseException; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.titov.parallel.file_map.BadFileException; +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; +import ru.fizteh.fivt.students.titov.parallel.storeable.AbstractStoreable; +import ru.fizteh.fivt.students.titov.parallel.storeable.TypesUtils; +import ru.fizteh.fivt.students.titov.parallel.storeable.Serializator; +import ru.fizteh.fivt.students.titov.parallel.shell.FileUtils; + +public class MFileHashMap implements TableProvider { + private String dataBaseDirectory; + private Map tables; + private FileMap currentTable; + private ReentrantReadWriteLock lockForCreateAndGet; + + public MFileHashMap(String newDirectory) throws BadFileException { + dataBaseDirectory = newDirectory; + tables = new HashMap<>(); + lockForCreateAndGet = new ReentrantReadWriteLock(); + init(); + } + + @Override + public Table getTable(String name) throws IllegalArgumentException { + if (name == null) { + throw new IllegalArgumentException("null argument"); + } + try { + lockForCreateAndGet.readLock().lock(); + Table returnValue; + if (tables.containsKey(name)) { + returnValue = tables.get(name); + } else { + returnValue = null; + } + return returnValue; + } finally { + lockForCreateAndGet.readLock().unlock(); + } + } + + @Override + public Table createTable(String name, List> columnTypes) throws IOException, IllegalArgumentException { + if (name == null || columnTypes == null) { + throw new IllegalArgumentException("null argument"); + } + TypesUtils.checkTypes(columnTypes); + + try { + lockForCreateAndGet.writeLock().lock(); + Table returnValue; + if (tables.containsKey(name)) { + returnValue = null; + } else { + Path pathOfNewTable = Paths.get(dataBaseDirectory, name); + Path pathOfNewTableSignatureFile = Paths.get(dataBaseDirectory, name, "signature.tsv"); + if (Files.exists(pathOfNewTable) & Files.isDirectory(pathOfNewTable)) { + throw new IllegalArgumentException("this directory already exists"); + } + Files.createDirectory(pathOfNewTable); + Files.createFile(pathOfNewTableSignatureFile); + try (FileWriter fileOut = new FileWriter(pathOfNewTableSignatureFile.toString())) { + fileOut.write(TypesUtils.toFileSignature(columnTypes)); + } + FileMap newTable = new FileMap(pathOfNewTable.toString(), columnTypes, this); + tables.put(name, newTable); + returnValue = newTable; + } + return returnValue; + } finally { + lockForCreateAndGet.writeLock().unlock(); + } + } + + @Override + public void removeTable(String name) throws IllegalArgumentException, IllegalStateException, IOException { + if (name == null) { + throw new IllegalArgumentException("null argument"); + } + try { + lockForCreateAndGet.writeLock().lock(); + if (tables.containsKey(name)) { + Path pathForRemoveTable = Paths.get(dataBaseDirectory, name); + tables.remove(name); + currentTable = null; + FileUtils.rmdir(pathForRemoveTable); + } else { + throw new IllegalStateException("table \'" + name + "\' doesn't exist"); + } + } finally { + lockForCreateAndGet.writeLock().unlock(); + } + } + + @Override + public Storeable createFor(Table table) { + Object[] startValues = new Object[table.getColumnsCount()]; + return new AbstractStoreable(startValues, table); + } + + @Override + public Storeable createFor(Table table, List values) throws ColumnFormatException, IndexOutOfBoundsException { + if (table.getColumnsCount() != values.size()) { + throw new IndexOutOfBoundsException("number of types"); + } + List objValues = new ArrayList<>(values); + List> typeList = new ArrayList<>(); + for (int i = 0; i < table.getColumnsCount(); ++i) { + if (objValues.get(i).getClass() != (table.getColumnType(i))) { + throw new ColumnFormatException("mismatch column type"); + } + typeList.add(table.getColumnType(i)); + } + TypesUtils.checkNewStorableValue(typeList, objValues); + return new AbstractStoreable(objValues.toArray(), table); + } + + @Override + public String serialize(Table table, Storeable value) throws ColumnFormatException { + if (table.getColumnsCount() != TypesUtils.getSizeOfStoreable(value)) { + throw new ColumnFormatException("wrong size"); + } + for (int i = 0; i < table.getColumnsCount(); ++i) { + if (!table.getColumnType(i).equals(value.getColumnAt(i).getClass())) { + throw new ColumnFormatException("need: " + table.getColumnType(i) + + ", but got:" + value.getColumnAt(i).getClass()); + } + } + return Serializator.serialize(table, value); + } + + @Override + public Storeable deserialize(Table table, String value) throws ParseException { + return Serializator.deserialize(table, value); + } + + @Override + public List getTableNames() { + List result = new ArrayList<>(); + Collection filemaps = tables.values(); + for (FileMap oneTable : filemaps) { + result.add(oneTable.getName()); + } + return result; + } + + public Map getTables() { + return tables; + } + + public void setCurrentTable(FileMap newCurrentTable) { + currentTable = newCurrentTable; + } + + public FileMap getCurrentTable() { + return currentTable; + } + + public boolean init() throws BadFileException { + String[] listOfFiles = new File(dataBaseDirectory).list(); + for (String oneFile: listOfFiles) { + Path oneTablePath = Paths.get(dataBaseDirectory, oneFile); + Path oneTableSignaturePath = Paths.get(dataBaseDirectory, oneFile, "signature.tsv"); + if (Files.isDirectory(oneTablePath) & Files.exists(oneTableSignaturePath)) { + try (Scanner input = new Scanner(oneTableSignaturePath)) { + String[] types; + if (input.hasNext()) { + types = input.nextLine().trim().split("\\s+"); + List> newTypeList = TypesUtils.toTypeList(types); + if (newTypeList != null) { + tables.put(oneFile, new FileMap(oneTablePath.toString(), newTypeList, this)); + } + } + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } + } + } + boolean allRight = true; + Set> pairSet = tables.entrySet(); + for (Entry oneFileMap: pairSet) { + if (!oneFileMap.getValue().init()) { + allRight = false; + } + } + return allRight; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MFileHashMapFactory.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MFileHashMapFactory.java new file mode 100644 index 000000000..528b68208 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MFileHashMapFactory.java @@ -0,0 +1,35 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.storage.structured.TableProviderFactory; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class MFileHashMapFactory implements TableProviderFactory { + public MFileHashMapFactory() {} + + public TableProvider create(String dir) throws IOException { + if (dir == null) { + throw new IllegalArgumentException(); + } + Path dataBaseDirectory + = Paths.get(System.getProperty("user.dir")).resolve(dir); + + if (Files.exists(dataBaseDirectory)) { + if (!Files.isDirectory(dataBaseDirectory)) { + throw new IllegalArgumentException(); + } + } else { + Files.createDirectory(dataBaseDirectory); + } + + MFileHashMap myMFileHashMap = new MFileHashMap(dataBaseDirectory.toString()); + if (!myMFileHashMap.init()) { + throw new IOException("error while initialization"); + } + return myMFileHashMap; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/Main.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/Main.java new file mode 100644 index 000000000..fe295ec3b --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/Main.java @@ -0,0 +1,77 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.BadFileException; +import ru.fizteh.fivt.students.titov.parallel.file_map.Shell; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Main { + private static final String PROJECTPROPERTY = "fizteh.db.dir"; + + public static void main(String[] args) throws BadFileException { + + if (System.getProperty(PROJECTPROPERTY) == null) { + System.err.println("we need working directory"); + System.exit(6); + } + Path dataBaseDirectory + = Paths.get(System.getProperty("user.dir")).resolve(System.getProperty(PROJECTPROPERTY)); + + boolean allRight = true; + if (Files.exists(dataBaseDirectory)) { + if (!Files.isDirectory(dataBaseDirectory)) { + System.err.println("working directory is a file"); + System.exit(4); + } + } else { + try { + Files.createDirectory(dataBaseDirectory); + } catch (IOException e) { + System.err.println("error while creating directory"); + allRight = false; + } finally { + if (!allRight) { + System.exit(5); + } + } + } + MFileHashMap myMFileHashMap = new MFileHashMap(dataBaseDirectory.toString()); + if (!myMFileHashMap.init()) { + System.exit(3); + } + + Shell myShell = new Shell<>(myMFileHashMap); + setUpShell(myShell); + + if (args.length > 0) { + allRight = myShell.batchMode(args); + } else { + allRight = myShell.interactiveMode(); + } + if (allRight) { + System.exit(0); + } else { + System.exit(1); + } + } + + + public static void setUpShell(Shell myShell) { + + myShell.addCommand(new CreateCommand()); + myShell.addCommand(new DropCommand()); + myShell.addCommand(new UseCommand()); + myShell.addCommand(new GetDistributeCommand()); + myShell.addCommand(new PutDistributeCommand()); + myShell.addCommand(new ListDistributeCommand()); + myShell.addCommand(new RemoveDistributeCommand()); + myShell.addCommand(new ShowTablesCommand()); + myShell.addCommand(new RollbackCommand()); + myShell.addCommand(new CommitCommand()); + myShell.addCommand(new SizeCommand()); + myShell.addCommand(new ExitCommand()); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MultiFileHashMapCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MultiFileHashMapCommand.java new file mode 100644 index 000000000..be67d19dc --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/MultiFileHashMapCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.Command; +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +public abstract class MultiFileHashMapCommand extends Command { + + public void initialize(String commandName, int n) { + name = commandName; + numberOfArguments = n; + } + + public boolean isTable(FileMap currentTable) { + if (currentTable == null) { + System.out.println("no table"); + return true; + } + return false; + } +} + diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/PutDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/PutDistributeCommand.java new file mode 100644 index 000000000..d631c039f --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/PutDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; +import ru.fizteh.fivt.students.titov.parallel.file_map.PutFileMapCommand; + +public class PutDistributeCommand extends MultiFileHashMapCommand { + public PutDistributeCommand() { + initialize("put", -1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + PutFileMapCommand commandPut = new PutFileMapCommand(); + return commandPut.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/RemoveDistributeCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/RemoveDistributeCommand.java new file mode 100644 index 000000000..32a734afe --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/RemoveDistributeCommand.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; +import ru.fizteh.fivt.students.titov.parallel.file_map.RemoveFileMapCommand; + +public class RemoveDistributeCommand extends MultiFileHashMapCommand { + public RemoveDistributeCommand() { + initialize("remove", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (myMap.getCurrentTable() == null) { + isTable(currentTable); + return true; + } + RemoveFileMapCommand removeCommand = new RemoveFileMapCommand(); + return removeCommand.run(currentTable, args); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/RollbackCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/RollbackCommand.java new file mode 100644 index 000000000..0148f31c9 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/RollbackCommand.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +public class RollbackCommand extends MultiFileHashMapCommand { + public RollbackCommand() { + initialize("rollback", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + isTable(currentTable); + } else { + System.out.println(currentTable.rollback()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ShowTablesCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ShowTablesCommand.java new file mode 100644 index 000000000..1f686ab3b --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/ShowTablesCommand.java @@ -0,0 +1,25 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +import java.util.Map.Entry; +import java.util.Set; + +public class ShowTablesCommand extends MultiFileHashMapCommand { + public ShowTablesCommand() { + initialize("show", 2); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + if (!args[1].equals("tables")) { + System.err.println(name + ": wrong arguments"); + return false; + } + Set> pairSet = myMap.getTables().entrySet(); + for (Entry oneTable: pairSet) { + System.out.println(oneTable.getKey() + " " + oneTable.getValue().size()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/SizeCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/SizeCommand.java new file mode 100644 index 000000000..945110980 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/SizeCommand.java @@ -0,0 +1,20 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +public class SizeCommand extends MultiFileHashMapCommand { + public SizeCommand() { + initialize("size", 1); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + isTable(currentTable); + } else { + System.out.println(currentTable.size()); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/UseCommand.java b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/UseCommand.java new file mode 100644 index 000000000..80f616bd9 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/multi_file_hash_map/UseCommand.java @@ -0,0 +1,30 @@ +package ru.fizteh.fivt.students.titov.parallel.multi_file_hash_map; + +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +public class UseCommand extends MultiFileHashMapCommand { + private static final String USING = "using "; + public UseCommand() { + initialize("use", 2); + } + + @Override + public boolean run(MFileHashMap myMap, String[] args) { + FileMap newCurrentTable = (FileMap) myMap.getTable(args[1]); + if (newCurrentTable != null) { + FileMap currentTable = myMap.getCurrentTable(); + if (currentTable == null) { + myMap.setCurrentTable(newCurrentTable); + System.out.println(USING + args[1]); + } else if (currentTable.getNumberOfUncommittedChanges() > 0) { + System.out.println(currentTable.getNumberOfUncommittedChanges() + " unsaved changes"); + } else { + myMap.setCurrentTable(newCurrentTable); + System.out.println(USING + args[1]); + } + } else { + System.out.println(args[1] + " not exists"); + } + return true; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/Command.java b/src/ru/fizteh/fivt/students/titov/parallel/shell/Command.java similarity index 83% rename from src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/Command.java rename to src/ru/fizteh/fivt/students/titov/parallel/shell/Command.java index a7250f9ec..3f5b20e7c 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/Command.java +++ b/src/ru/fizteh/fivt/students/titov/parallel/shell/Command.java @@ -1,4 +1,4 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; +package ru.fizteh.fivt.students.titov.parallel.shell; public abstract class Command { protected String name; diff --git a/src/ru/fizteh/fivt/students/titov/parallel/shell/FileUtils.java b/src/ru/fizteh/fivt/students/titov/parallel/shell/FileUtils.java new file mode 100644 index 000000000..2742ae084 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/shell/FileUtils.java @@ -0,0 +1,23 @@ +package ru.fizteh.fivt.students.titov.parallel.shell; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class FileUtils { + public static boolean mkdir(Path newDirectory) { + MkdirCommand command = new MkdirCommand(); + String[] args = {"mkdir", + newDirectory.toString() + }; + return command.run(args); + } + + public static void rmdir(Path newDirectory) throws IOException { + if (!Files.isDirectory(newDirectory) | !Files.exists(newDirectory)) { + throw new IllegalArgumentException(); + } + FileVisitorDelete myFileVisitorDelete = new FileVisitorDelete(); + Files.walkFileTree(newDirectory, myFileVisitorDelete); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileVisitorDelete.java b/src/ru/fizteh/fivt/students/titov/parallel/shell/FileVisitorDelete.java similarity index 58% rename from src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileVisitorDelete.java rename to src/ru/fizteh/fivt/students/titov/parallel/shell/FileVisitorDelete.java index 9c1f8794b..a7569d1f9 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/FileVisitorDelete.java +++ b/src/ru/fizteh/fivt/students/titov/parallel/shell/FileVisitorDelete.java @@ -1,4 +1,4 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; +package ru.fizteh.fivt.students.titov.parallel.shell; import java.io.IOException; import java.nio.file.FileVisitResult; @@ -12,12 +12,8 @@ public class FileVisitorDelete extends SimpleFileVisitor { @Override - public FileVisitResult visitFile(final Path filePath, final BasicFileAttributes attr) { - try { - Files.delete(filePath.toAbsolutePath()); - } catch (IOException e) { - System.err.println("IOException: " + filePath.toAbsolutePath().toString()); - } + public FileVisitResult visitFile(final Path filePath, final BasicFileAttributes attr) throws IOException { + Files.delete(filePath.toAbsolutePath()); return CONTINUE; } @@ -28,12 +24,8 @@ public FileVisitResult visitFileFailed(final Path filePath, final IOException ex } @Override - public FileVisitResult postVisitDirectory(final Path directoryPath, final IOException exc) { - try { - Files.delete(directoryPath.toAbsolutePath()); - } catch (IOException e) { - System.err.println("IOException " + directoryPath.toAbsolutePath().toString()); - } + public FileVisitResult postVisitDirectory(final Path directoryPath, final IOException exc) throws IOException { + Files.delete(directoryPath.toAbsolutePath()); return CONTINUE; } } diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCat.java b/src/ru/fizteh/fivt/students/titov/parallel/shell/MkdirCommand.java similarity index 52% rename from src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCat.java rename to src/ru/fizteh/fivt/students/titov/parallel/shell/MkdirCommand.java index a9d7e1823..1005a69c3 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandCat.java +++ b/src/ru/fizteh/fivt/students/titov/parallel/shell/MkdirCommand.java @@ -1,11 +1,10 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; +package ru.fizteh.fivt.students.titov.parallel.shell; -import java.nio.file.FileSystems; import java.nio.file.Files; -public class CommandCat extends Command { - public CommandCat() { - name = "cat"; +public class MkdirCommand extends ru.fizteh.fivt.students.titov.parallel.shell.Command { + public MkdirCommand() { + name = "mkdir"; numberOfArguments = 2; } @@ -16,9 +15,8 @@ public boolean run(final String[] arguments) { return false; } try { - Files.copy(FileSystems.getDefault().getPath(arguments[1]), System.out); + Files.createDirectory(PathsFunction.toAbsolutePathString(arguments[1])); } catch (Exception e) { - System.out.println(name + ": " + arguments[1] + ": No such file in directory"); return false; } return true; diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/PathsFunction.java b/src/ru/fizteh/fivt/students/titov/parallel/shell/PathsFunction.java similarity index 81% rename from src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/PathsFunction.java rename to src/ru/fizteh/fivt/students/titov/parallel/shell/PathsFunction.java index 9318ce6b7..2db069e8e 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/PathsFunction.java +++ b/src/ru/fizteh/fivt/students/titov/parallel/shell/PathsFunction.java @@ -1,13 +1,14 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; +package ru.fizteh.fivt.students.titov.parallel.shell; import java.nio.file.Paths; import java.nio.file.Path; +import java.io.File; public class PathsFunction { public static Path toAbsolutePathString(final String myPath) { String absolutePathString; - String fileSeparator = System.getProperty("file.separator"); + String fileSeparator = File.separator; if (Paths.get(myPath).isAbsolute()) { absolutePathString = myPath; } else { diff --git a/src/ru/fizteh/fivt/students/titov/parallel/storeable/AbstractStoreable.java b/src/ru/fizteh/fivt/students/titov/parallel/storeable/AbstractStoreable.java new file mode 100644 index 000000000..fb21c28cc --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/storeable/AbstractStoreable.java @@ -0,0 +1,97 @@ +package ru.fizteh.fivt.students.titov.parallel.storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; + +public class AbstractStoreable implements Storeable { + private Object[] values; + private Table parentTable; + + public AbstractStoreable(Object[] newValues, Table newParent) { + values = newValues; + parentTable = newParent; + } + + @Override + public void setColumnAt(int columnIndex, Object value) throws ColumnFormatException, IndexOutOfBoundsException { + if (value == null) { + values[columnIndex] = value; + return; + } + if (!parentTable.getColumnType(columnIndex).equals(value.getClass())) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + value.getClass()); + } else { + values[columnIndex] = value; + } + } + + @Override + public Object getColumnAt(int columnIndex) throws IndexOutOfBoundsException { + return values[columnIndex]; + } + + @Override + public Integer getIntAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Integer.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Integer.class); + } + return (Integer) values[columnIndex]; + } + + @Override + public Long getLongAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Long.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Long.class); + } + return (Long) values[columnIndex]; + } + + @Override + public Byte getByteAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Byte.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Byte.class); + } + return (Byte) values[columnIndex]; + } + + @Override + public Float getFloatAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Float.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Float.class); + } + return (Float) values[columnIndex]; + } + + @Override + public Double getDoubleAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Double.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Double.class); + } + return (Double) values[columnIndex]; + } + + @Override + public Boolean getBooleanAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Boolean.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Boolean.class); + } + return (Boolean) values[columnIndex]; + } + + @Override + public String getStringAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(String.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + String.class); + } + return (String) values[columnIndex]; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/storeable/Serializator.java b/src/ru/fizteh/fivt/students/titov/parallel/storeable/Serializator.java new file mode 100644 index 000000000..3f0db18f4 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/storeable/Serializator.java @@ -0,0 +1,114 @@ +package ru.fizteh.fivt.students.titov.parallel.storeable; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.students.titov.parallel.file_map.FileMap; + +import javax.xml.stream.*; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +public class Serializator { + interface GetSmthSer { + Object get(int index); + } + + interface GetSmthDeser { + Object get(String s) throws IllegalArgumentException; + } + + private static Map, GetSmthSer> toFindApproriateSer; + private static Map, GetSmthDeser> toFindApproriateDeser; + static { + toFindApproriateSer = new HashMap<>(); + toFindApproriateDeser = new HashMap<>(); + + toFindApproriateDeser.put(Integer.class, Integer::parseInt); + toFindApproriateDeser.put(Long.class, Long::parseLong); + toFindApproriateDeser.put(Byte.class, Byte::parseByte); + toFindApproriateDeser.put(Float.class, Float::parseFloat); + toFindApproriateDeser.put(Double.class, Double::parseDouble); + toFindApproriateDeser.put(Boolean.class, Boolean::parseBoolean); + toFindApproriateDeser.put(String.class, String::toString); + } + + public static String serialize(Table table, Storeable value) { + toFindApproriateSer.put(Integer.class, value::getIntAt); + toFindApproriateSer.put(Long.class, value::getLongAt); + toFindApproriateSer.put(Byte.class, value::getByteAt); + toFindApproriateSer.put(Float.class, value::getFloatAt); + toFindApproriateSer.put(Double.class, value::getDoubleAt); + toFindApproriateSer.put(Boolean.class, value::getBooleanAt); + toFindApproriateSer.put(String.class, value::getStringAt); + + StringWriter stringWriter = new StringWriter(); + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + try { + XMLStreamWriter writer = factory.createXMLStreamWriter(stringWriter); + writer.writeStartElement("row"); + for (int i = 0; i < table.getColumnsCount(); ++i) { + String valueInColumn; + if (value.getColumnAt(i) == null) { + writer.writeEmptyElement("null"); + } else { + writer.writeStartElement("col"); + valueInColumn = toFindApproriateSer.get(table.getColumnType(i)).get(i).toString(); + writer.writeCharacters(valueInColumn); + writer.writeEndElement(); + } + } + writer.writeEndElement(); + writer.flush(); + } catch (XMLStreamException e) { + return null; + } + return stringWriter.toString(); + } + + public static Storeable deserialize(Table table, String valueXML) throws ParseException { + byte[] byteArray = valueXML.getBytes(); + Storeable result = ((FileMap) table).getTableProvider().createFor(table); + ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray); + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + try { + XMLEventReader reader = inputFactory.createXMLEventReader(inputStream); + int count = 0; + while (reader.hasNext()) { + XMLEvent event = (XMLEvent) reader.next(); + if (event.isStartElement()) { + StartElement element = event.asStartElement(); + if (element.getName().getLocalPart().equals("col")) { + event = (XMLEvent) reader.next(); + if (event.isCharacters()) { + String newValue = event.asCharacters().getData(); + try { + result.setColumnAt(count, + toFindApproriateDeser.get(table.getColumnType(count)).get(newValue)); + } catch (NumberFormatException e) { + throw new ParseException(e.getMessage(), count); + } + ++count; + } + } else if (element.getName().getLocalPart().equals("null")) { + result.setColumnAt(count, null); + ++count; + } else if (!element.getName().getLocalPart().equals("row")) { + throw new ParseException(element.toString(), count); + } + } + } + } catch (XMLStreamException e) { + throw new ParseException(e.getMessage(), -1); + } catch (NoSuchElementException e) { + throw new ParseException(e.getMessage(), -1); + } + return result; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/parallel/storeable/TypesUtils.java b/src/ru/fizteh/fivt/students/titov/parallel/storeable/TypesUtils.java new file mode 100644 index 000000000..c0037f595 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/parallel/storeable/TypesUtils.java @@ -0,0 +1,136 @@ +package ru.fizteh.fivt.students.titov.parallel.storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class TypesUtils { + public static HashSet> canonicalTypes; + + static { + canonicalTypes = new HashSet<>(); + canonicalTypes.add(Integer.class); + canonicalTypes.add(Long.class); + canonicalTypes.add(Byte.class); + canonicalTypes.add(Float.class); + canonicalTypes.add(Double.class); + canonicalTypes.add(Boolean.class); + canonicalTypes.add(String.class); + } + + public static void checkTypes(List> types) { + for (Class oneClass : types) { + if (!canonicalTypes.contains(oneClass)) { + throw new IllegalArgumentException("wrong type (" + oneClass.getTypeName() + ")"); + } + } + } + + public static void checkNewStorableValue(List> types, Storeable newValue) + throws IndexOutOfBoundsException { + if (types.size() != TypesUtils.getSizeOfStoreable(newValue)) { + throw new IndexOutOfBoundsException(); + } + List valueList = new ArrayList<>(); + for (int i = 0; i < types.size(); ++i) { + valueList.add(newValue.getColumnAt(i)); + } + checkNewStorableValue(types, valueList); + } + + public static void checkNewStorableValue(List> types, List newValue) + throws ColumnFormatException, IndexOutOfBoundsException { + if (types.size() != newValue.size()) { + throw new IndexOutOfBoundsException(); + } + for (int i = 0; i < types.size(); ++i) { + if (newValue.get(i) != null + && !newValue.get(i).getClass().equals(types.get(i))) { + throw new ColumnFormatException(newValue.get(i).getClass().toString()); + } + } + } + + public static List> toTypeList(String[] types) throws ColumnFormatException { + List> result = new ArrayList<>(); + for (String oneType : types) { + switch(oneType) { + case "int": + result.add(Integer.class); + break; + case "long": + result.add(Long.class); + break; + case "byte": + result.add(Byte.class); + break; + case "float": + result.add(Float.class); + break; + case "double": + result.add(Double.class); + break; + case "boolean": + result.add(Boolean.class); + break; + case "String": + result.add(String.class); + break; + default: + throw new ColumnFormatException("wrong type (" + oneType + ")"); + } + } + return result; + } + + public static String toFileSignature(List> types) { + StringBuilder s = new StringBuilder(); + int counter = 0; + for (Class oneClass : types) { + if (counter > 0) { + s.append(" "); + } + switch (oneClass.getTypeName()) { + case "java.lang.Integer": + s.append("int"); + break; + case "java.lang.Byte": + s.append("byte"); + break; + case "java.lang.Long": + s.append("long"); + break; + case "java.lang.Boolean": + s.append("boolean"); + break; + case "java.lang.Float": + s.append("float"); + break; + case "java.lang.Double": + s.append("double"); + break; + case "java.lang.String": + s.append("String"); + break; + default: + return null; + } + ++counter; + } + return s.toString(); + } + + + public static int getSizeOfStoreable(Storeable obj) { + for (int i = 0; ; ++i) { + try { + obj.getColumnAt(i); + } catch (IndexOutOfBoundsException e) { + return i; + } + } + } +} diff --git a/src/ru/fizteh/fivt/students/titov/shell/Command.java b/src/ru/fizteh/fivt/students/titov/shell/Command.java new file mode 100644 index 000000000..635b7e53b --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/shell/Command.java @@ -0,0 +1,17 @@ +package ru.fizteh.fivt.students.titov.shell; + +public abstract class Command { + protected String name; + protected int numberOfArguments; + + public abstract boolean run(final String[] arguments); + + public final String getName() { + return name; + } + + @Override + public final String toString() { + return name; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/shell/FileUtils.java b/src/ru/fizteh/fivt/students/titov/shell/FileUtils.java new file mode 100644 index 000000000..31f18f6f0 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/shell/FileUtils.java @@ -0,0 +1,23 @@ +package ru.fizteh.fivt.students.titov.shell; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class FileUtils { + public static boolean mkdir(Path newDirectory) { + MkdirCommand command = new MkdirCommand(); + String[] args = {"mkdir", + newDirectory.toString() + }; + return command.run(args); + } + + public static void rmdir(Path newDirectory) throws IOException { + if (!Files.isDirectory(newDirectory) | !Files.exists(newDirectory)) { + throw new IllegalArgumentException(); + } + FileVisitorDelete myFileVisitorDelete = new FileVisitorDelete(); + Files.walkFileTree(newDirectory, myFileVisitorDelete); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/shell/FileVisitorDelete.java b/src/ru/fizteh/fivt/students/titov/shell/FileVisitorDelete.java new file mode 100644 index 000000000..cfb0f3e89 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/shell/FileVisitorDelete.java @@ -0,0 +1,31 @@ +package ru.fizteh.fivt.students.titov.shell; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.SimpleFileVisitor; + +import static java.nio.file.FileVisitResult.*; + +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; + +public class FileVisitorDelete extends SimpleFileVisitor { + @Override + public FileVisitResult visitFile(final Path filePath, final BasicFileAttributes attr) throws IOException { + Files.delete(filePath.toAbsolutePath()); + return CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(final Path filePath, final IOException exc) { + System.err.println("Error occuried while visitтпg file"); + return CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(final Path directoryPath, final IOException exc) throws IOException { + Files.delete(directoryPath.toAbsolutePath()); + return CONTINUE; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandMkdir.java b/src/ru/fizteh/fivt/students/titov/shell/MkdirCommand.java similarity index 76% rename from src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandMkdir.java rename to src/ru/fizteh/fivt/students/titov/shell/MkdirCommand.java index 253c152a3..e8295dc16 100644 --- a/src/ru/fizteh/fivt/students/titov/JUnit/ShellPackage/CommandMkdir.java +++ b/src/ru/fizteh/fivt/students/titov/shell/MkdirCommand.java @@ -1,9 +1,9 @@ -package ru.fizteh.fivt.students.titov.JUnit.ShellPackage; +package ru.fizteh.fivt.students.titov.shell; import java.nio.file.Files; -public class CommandMkdir extends Command { - public CommandMkdir() { +public class MkdirCommand extends ru.fizteh.fivt.students.titov.shell.Command { + public MkdirCommand() { name = "mkdir"; numberOfArguments = 2; } diff --git a/src/ru/fizteh/fivt/students/titov/shell/PathsFunction.java b/src/ru/fizteh/fivt/students/titov/shell/PathsFunction.java new file mode 100644 index 000000000..4ccb489c9 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/shell/PathsFunction.java @@ -0,0 +1,21 @@ +package ru.fizteh.fivt.students.titov.shell; + +import java.nio.file.Paths; +import java.nio.file.Path; +import java.io.File; + +public class PathsFunction { + + public static Path toAbsolutePathString(final String myPath) { + String absolutePathString; + String fileSeparator = File.separator; + if (Paths.get(myPath).isAbsolute()) { + absolutePathString = myPath; + } else { + absolutePathString = System.getProperty("user.dir") + + fileSeparator + myPath; + } + absolutePathString = Paths.get(absolutePathString).normalize().toString(); + return Paths.get(absolutePathString); + } +} diff --git a/src/ru/fizteh/fivt/students/titov/storeable/AbstractStoreable.java b/src/ru/fizteh/fivt/students/titov/storeable/AbstractStoreable.java new file mode 100644 index 000000000..7d76c4986 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/storeable/AbstractStoreable.java @@ -0,0 +1,97 @@ +package ru.fizteh.fivt.students.titov.storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; + +public class AbstractStoreable implements Storeable { + private Object[] values; + private Table parentTable; + + public AbstractStoreable(Object[] newValues, Table newParent) { + values = newValues; + parentTable = newParent; + } + + @Override + public void setColumnAt(int columnIndex, Object value) throws ColumnFormatException, IndexOutOfBoundsException { + if (value == null) { + values[columnIndex] = value; + return; + } + if (!parentTable.getColumnType(columnIndex).equals(value.getClass())) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + value.getClass()); + } else { + values[columnIndex] = value; + } + } + + @Override + public Object getColumnAt(int columnIndex) throws IndexOutOfBoundsException { + return values[columnIndex]; + } + + @Override + public Integer getIntAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Integer.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Integer.class); + } + return (Integer) values[columnIndex]; + } + + @Override + public Long getLongAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Long.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Long.class); + } + return (Long) values[columnIndex]; + } + + @Override + public Byte getByteAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Byte.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Byte.class); + } + return (Byte) values[columnIndex]; + } + + @Override + public Float getFloatAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Float.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Float.class); + } + return (Float) values[columnIndex]; + } + + @Override + public Double getDoubleAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Double.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Double.class); + } + return (Double) values[columnIndex]; + } + + @Override + public Boolean getBooleanAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(Boolean.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + Boolean.class); + } + return (Boolean) values[columnIndex]; + } + + @Override + public String getStringAt(int columnIndex) throws ColumnFormatException, IndexOutOfBoundsException { + if (!values[columnIndex].getClass().equals(String.class)) { + throw new ColumnFormatException("expected:" + parentTable.getColumnType(columnIndex) + + " , but got:" + String.class); + } + return (String) values[columnIndex]; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/storeable/Serializator.java b/src/ru/fizteh/fivt/students/titov/storeable/Serializator.java new file mode 100644 index 000000000..bdbc9d901 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/storeable/Serializator.java @@ -0,0 +1,114 @@ +package ru.fizteh.fivt.students.titov.storeable; + +import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.storage.structured.Table; +import ru.fizteh.fivt.students.titov.file_map.FileMap; + +import javax.xml.stream.*; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +public class Serializator { + interface GetSmthSer { + Object get(int index); + } + + interface GetSmthDeser { + Object get(String s) throws IllegalArgumentException; + } + + private static Map, GetSmthSer> toFindApproriateSer; + private static Map, GetSmthDeser> toFindApproriateDeser; + static { + toFindApproriateSer = new HashMap<>(); + toFindApproriateDeser = new HashMap<>(); + + toFindApproriateDeser.put(Integer.class, Integer::parseInt); + toFindApproriateDeser.put(Long.class, Long::parseLong); + toFindApproriateDeser.put(Byte.class, Byte::parseByte); + toFindApproriateDeser.put(Float.class, Float::parseFloat); + toFindApproriateDeser.put(Double.class, Double::parseDouble); + toFindApproriateDeser.put(Boolean.class, Boolean::parseBoolean); + toFindApproriateDeser.put(String.class, String::toString); + } + + public static String serialize(Table table, Storeable value) { + toFindApproriateSer.put(Integer.class, value::getIntAt); + toFindApproriateSer.put(Long.class, value::getLongAt); + toFindApproriateSer.put(Byte.class, value::getByteAt); + toFindApproriateSer.put(Float.class, value::getFloatAt); + toFindApproriateSer.put(Double.class, value::getDoubleAt); + toFindApproriateSer.put(Boolean.class, value::getBooleanAt); + toFindApproriateSer.put(String.class, value::getStringAt); + + StringWriter stringWriter = new StringWriter(); + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + try { + XMLStreamWriter writer = factory.createXMLStreamWriter(stringWriter); + writer.writeStartElement("row"); + for (int i = 0; i < table.getColumnsCount(); ++i) { + String valueInColumn; + if (value.getColumnAt(i) == null) { + writer.writeEmptyElement("null"); + } else { + writer.writeStartElement("col"); + valueInColumn = toFindApproriateSer.get(table.getColumnType(i)).get(i).toString(); + writer.writeCharacters(valueInColumn); + writer.writeEndElement(); + } + } + writer.writeEndElement(); + writer.flush(); + } catch (XMLStreamException e) { + return null; + } + return stringWriter.toString(); + } + + public static Storeable deserialize(Table table, String valueXML) throws ParseException { + byte[] byteArray = valueXML.getBytes(); + Storeable result = ((FileMap) table).getTableProvider().createFor(table); + ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray); + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + try { + XMLEventReader reader = inputFactory.createXMLEventReader(inputStream); + int count = 0; + while (reader.hasNext()) { + XMLEvent event = (XMLEvent) reader.next(); + if (event.isStartElement()) { + StartElement element = event.asStartElement(); + if (element.getName().getLocalPart().equals("col")) { + event = (XMLEvent) reader.next(); + if (event.isCharacters()) { + String newValue = event.asCharacters().getData(); + try { + result.setColumnAt(count, + toFindApproriateDeser.get(table.getColumnType(count)).get(newValue)); + } catch (NumberFormatException e) { + throw new ParseException(e.getMessage(), count); + } + ++count; + } + } else if (element.getName().getLocalPart().equals("null")) { + result.setColumnAt(count, null); + ++count; + } else if (!element.getName().getLocalPart().equals("row")) { + throw new ParseException(element.toString(), count); + } + } + } + } catch (XMLStreamException e) { + throw new ParseException(e.getMessage(), -1); + } catch (NoSuchElementException e) { + throw new ParseException(e.getMessage(), -1); + } + return result; + } +} diff --git a/src/ru/fizteh/fivt/students/titov/storeable/TypesUtils.java b/src/ru/fizteh/fivt/students/titov/storeable/TypesUtils.java new file mode 100644 index 000000000..b747eb289 --- /dev/null +++ b/src/ru/fizteh/fivt/students/titov/storeable/TypesUtils.java @@ -0,0 +1,136 @@ +package ru.fizteh.fivt.students.titov.storeable; + +import ru.fizteh.fivt.storage.structured.ColumnFormatException; +import ru.fizteh.fivt.storage.structured.Storeable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class TypesUtils { + public static HashSet> canonicalTypes; + + static { + canonicalTypes = new HashSet<>(); + canonicalTypes.add(Integer.class); + canonicalTypes.add(Long.class); + canonicalTypes.add(Byte.class); + canonicalTypes.add(Float.class); + canonicalTypes.add(Double.class); + canonicalTypes.add(Boolean.class); + canonicalTypes.add(String.class); + } + + public static void checkTypes(List> types) { + for (Class oneClass : types) { + if (!canonicalTypes.contains(oneClass)) { + throw new IllegalArgumentException("wrong type (" + oneClass.getTypeName() + ")"); + } + } + } + + public static void checkNewStorableValue(List> types, Storeable newValue) + throws IndexOutOfBoundsException { + if (types.size() != TypesUtils.getSizeOfStoreable(newValue)) { + throw new IndexOutOfBoundsException(); + } + List valueList = new ArrayList<>(); + for (int i = 0; i < types.size(); ++i) { + valueList.add(newValue.getColumnAt(i)); + } + checkNewStorableValue(types, valueList); + } + + public static void checkNewStorableValue(List> types, List newValue) + throws ColumnFormatException, IndexOutOfBoundsException { + if (types.size() != newValue.size()) { + throw new IndexOutOfBoundsException(); + } + for (int i = 0; i < types.size(); ++i) { + if (newValue.get(i) != null + && !newValue.get(i).getClass().equals(types.get(i))) { + throw new ColumnFormatException(newValue.get(i).getClass().toString()); + } + } + } + + public static List> toTypeList(String[] types) throws ColumnFormatException { + List> result = new ArrayList<>(); + for (String oneType : types) { + switch(oneType) { + case "int": + result.add(Integer.class); + break; + case "long": + result.add(Long.class); + break; + case "byte": + result.add(Byte.class); + break; + case "float": + result.add(Float.class); + break; + case "double": + result.add(Double.class); + break; + case "boolean": + result.add(Boolean.class); + break; + case "String": + result.add(String.class); + break; + default: + throw new ColumnFormatException("wrong type (" + oneType + ")"); + } + } + return result; + } + + public static String toFileSignature(List> types) { + StringBuilder s = new StringBuilder(); + int counter = 0; + for (Class oneClass : types) { + if (counter > 0) { + s.append(" "); + } + switch (oneClass.getTypeName()) { + case "java.lang.Integer": + s.append("int"); + break; + case "java.lang.Byte": + s.append("byte"); + break; + case "java.lang.Long": + s.append("long"); + break; + case "java.lang.Boolean": + s.append("boolean"); + break; + case "java.lang.Float": + s.append("float"); + break; + case "java.lang.Double": + s.append("double"); + break; + case "java.lang.String": + s.append("String"); + break; + default: + return null; + } + ++counter; + } + return s.toString(); + } + + + public static int getSizeOfStoreable(Storeable obj) { + for (int i = 0; ; ++i) { + try { + obj.getColumnAt(i); + } catch (IndexOutOfBoundsException e) { + return i; + } + } + } +}