diff --git a/lesson/lesson1.md b/lesson/lesson1.md index 6c2f6331..67f78ff0 100644 --- a/lesson/lesson1.md +++ b/lesson/lesson1.md @@ -67,7 +67,7 @@ ![Screenshot_5](https://user-images.githubusercontent.com/29703461/199550057-fce7cf3c-7040-422f-b490-7b85b47ae952.png) -- Реализуйте методы `save, get, delete, clear, getAll, size` в классе `ArrayStorage`, организовав хранение резюме в массиве +- Реализуйте методы `save, get, delete, clear, getAll, size` в классе `com.urise.webapp.storage.ArrayStorage`, организовав хранение резюме в массиве - Храните все резюме в начале `storage` (без пустот в виде `null`), чтобы не перебирать каждый раз все 10_000 элементов - При реализации метода `delete` учитывайте, что после удаления резюме между оставшимися резюме не должно быть пустых ячеек, заполненных null ``` @@ -77,7 +77,7 @@ r1, r2, r3,..., rn, null, null,..., null <----- size -----> <------- storage.length (10000) -------> ``` -- Проверьте вашу реализацию с помощью классов `MainArray.main()` и `MainTestArrayStorage.main()` +- Проверьте вашу реализацию с помощью классов `com.urise.webapp.MainArray.main()` и `com.urise.webapp.MainTestArrayStorage.main()` - Изучите дополнительные материалы по IntelliJ IDEA: - [Idea Wiki](https://github.com/JavaOPs/topjava/wiki/IDEA) - [Отладка Java кода в IDEA. Основные возможности отладчика](https://youtu.be/Z1BQsf0A4xY) @@ -96,11 +96,11 @@ r1, r2, r3,..., rn, null, null,..., null 1. Перед каждым коммитом не забывайте пользоваться сочетанием клавиш `Ctrl + Alt + L` (автоматическое форматирование кода) 1. Удаляйте в классах неиспользуемые импорты (`Ctrl + Alt + O`) 1. Не игнорируй подсказки IDEA (подсвечивает) -1. В методе `clear()` обнуление массива предполагает обнуление (null) ячеек, где хранятся Resume, а не создание нового или присваивание ему null +1. В методе `clear()` обнуление массива предполагает обнуление (null) ячеек, где хранятся com.urise.webapp.model.Resume, а не создание нового или присваивание ему null 1. При реализации методов не используйте коллекции -1. Не меняйте сигнатуры методов в `ArrayStorage` -1. Не добавляйте в `Resume` новые поля -1. Resume r — давайте переменным осмысленные имена, например resume. r допустимо в коротких циклах и лямбда-выражениях +1. Не меняйте сигнатуры методов в `com.urise.webapp.storage.ArrayStorage` +1. Не добавляйте в `com.urise.webapp.model.Resume` новые поля +1. com.urise.webapp.model.Resume r — давайте переменным осмысленные имена, например resume. r допустимо в коротких циклах и лямбда-выражениях ## ![video](https://cloud.githubusercontent.com/assets/13649199/13672715/06dbc6ce-e6e7-11e5-81a9-04fbddb9e488.png) 5. [Вебинар "Быть программистом: от детства к зрелости"](https://www.youtube.com/watch?v=D5Hej0TyLaU) - [Слайды вебинара](https://docs.google.com/presentation/d/1YwtCCZsaGMdl-V15kTDHiJxiS52IAl-qqheNPpiNr54/) diff --git a/src/ArrayStorage.java b/src/ArrayStorage.java deleted file mode 100644 index 7aff0388..00000000 --- a/src/ArrayStorage.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Array based storage for Resumes - */ -public class ArrayStorage { - Resume[] storage = new Resume[10000]; - - void clear() { - } - - void save(Resume r) { - } - - Resume get(String uuid) { - return null; - } - - void delete(String uuid) { - } - - /** - * @return array, contains only Resumes in storage (without null) - */ - Resume[] getAll() { - return new Resume[0]; - } - - int size() { - return 0; - } -} diff --git a/src/MainTestArrayStorage.java b/src/MainTestArrayStorage.java deleted file mode 100644 index b15b81e2..00000000 --- a/src/MainTestArrayStorage.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Test for your ArrayStorage implementation - */ -public class MainTestArrayStorage { - static final ArrayStorage ARRAY_STORAGE = new ArrayStorage(); - - public static void main(String[] args) { - Resume r1 = new Resume(); - r1.uuid = "uuid1"; - Resume r2 = new Resume(); - r2.uuid = "uuid2"; - Resume r3 = new Resume(); - r3.uuid = "uuid3"; - - ARRAY_STORAGE.save(r1); - ARRAY_STORAGE.save(r2); - ARRAY_STORAGE.save(r3); - - System.out.println("Get r1: " + ARRAY_STORAGE.get(r1.uuid)); - System.out.println("Size: " + ARRAY_STORAGE.size()); - - System.out.println("Get dummy: " + ARRAY_STORAGE.get("dummy")); - - printAll(); - ARRAY_STORAGE.delete(r1.uuid); - printAll(); - ARRAY_STORAGE.clear(); - printAll(); - - System.out.println("Size: " + ARRAY_STORAGE.size()); - } - - static void printAll() { - System.out.println("\nGet All"); - for (Resume r : ARRAY_STORAGE.getAll()) { - System.out.println(r); - } - } -} diff --git a/src/Resume.java b/src/Resume.java deleted file mode 100644 index 8de4e4b8..00000000 --- a/src/Resume.java +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Initial resume class - */ -public class Resume { - - // Unique identifier - String uuid; - - @Override - public String toString() { - return uuid; - } -} diff --git a/src/MainArray.java b/src/com/urise/webapp/MainArray.java similarity index 85% rename from src/MainArray.java rename to src/com/urise/webapp/MainArray.java index 063364db..e4e2d6c6 100644 --- a/src/MainArray.java +++ b/src/com/urise/webapp/MainArray.java @@ -1,9 +1,14 @@ +package com.urise.webapp; + +import com.urise.webapp.model.Resume; +import com.urise.webapp.storage.ArrayStorage; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** - * Interactive test for ArrayStorage implementation + * Interactive test for com.urise.webapp.storage.ArrayStorage implementation * (just run, no need to understand) */ public class MainArray { @@ -13,7 +18,7 @@ public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); Resume r; while (true) { - System.out.print("Введите одну из команд - (list | size | save uuid | delete uuid | get uuid | clear | exit): "); + System.out.print("Введите одну из команд - (list | size | save uuid | delete uuid | get uuid | clear | update | exit): "); String[] params = reader.readLine().trim().toLowerCase().split(" "); if (params.length < 1 || params.length > 2) { System.out.println("Неверная команда."); @@ -31,8 +36,7 @@ public static void main(String[] args) throws IOException { System.out.println(ARRAY_STORAGE.size()); break; case "save": - r = new Resume(); - r.uuid = uuid; + r = new Resume(uuid); ARRAY_STORAGE.save(r); printAll(); break; @@ -47,8 +51,13 @@ public static void main(String[] args) throws IOException { ARRAY_STORAGE.clear(); printAll(); break; + case "update": + r = new Resume(uuid); + ARRAY_STORAGE.update(r); + break; case "exit": return; + default: System.out.println("Неверная команда."); break; diff --git a/src/com/urise/webapp/MainCollections.java b/src/com/urise/webapp/MainCollections.java new file mode 100644 index 00000000..6ba2135b --- /dev/null +++ b/src/com/urise/webapp/MainCollections.java @@ -0,0 +1,108 @@ +package com.urise.webapp; + +import com.urise.webapp.model.Resume; +import com.urise.webapp.storage.AbstractStorage; +import com.urise.webapp.storage.MapStorage; + +import java.util.*; + +public class MainCollections { + private static final String UUID_1 = "uuid1"; + private static final Resume RESUME_1 = new Resume(UUID_1); + + private static final String UUID_2 = "uuid2"; + private static final Resume RESUME_2 = new Resume(UUID_2); + + private static final String UUID_3 = "uuid3"; + private static final Resume RESUME_3 = new Resume(UUID_3); + + private static final String UUID_4 = "uuid4"; + private static final Resume RESUME_4 = new Resume(UUID_4); + // private static final Resume UUID_NOT_EXIST = new Resume("dummy"); +// private static final AbstractStorage ABSTRACT_STORAGE = new ListStorage(); + private static final AbstractStorage ABSTRACT_STORAGE = new MapStorage(); + + public static void main(String[] args) { + ABSTRACT_STORAGE.save(RESUME_1); + ABSTRACT_STORAGE.save(RESUME_2); + ABSTRACT_STORAGE.save(RESUME_3); + ABSTRACT_STORAGE.getAll(); + printAll(); + + System.out.println("Get r1: " + ABSTRACT_STORAGE.get(RESUME_1.getUuid())); + System.out.println("Size: " + ABSTRACT_STORAGE.size()); + + // System.out.println("Get dummy: " + ABSTRACT_STORAGE.get(UUID_NOT_EXIST.getUuid())); + + ABSTRACT_STORAGE.update(RESUME_2); + System.out.println("ok update"); + printAll(); + System.out.println("--------"); + + ABSTRACT_STORAGE.save(RESUME_4); + System.out.println("ok save"); + printAll(); + System.out.println("--------"); + + ABSTRACT_STORAGE.delete(RESUME_3.getUuid()); + System.out.println("ok delete"); + printAll(); + System.out.println("--------"); + + ABSTRACT_STORAGE.clear(); + System.out.println("ok clear"); + printAll(); + System.out.println("--------"); + + System.out.println("Size: " + ABSTRACT_STORAGE.size()); + ABSTRACT_STORAGE.size(); + + + System.out.println("Collection"); + Collection collection = new ArrayList<>(); + collection.add(RESUME_1); + collection.add(RESUME_2); + collection.add(RESUME_3); + + for (Resume r : collection) { + System.out.println(r); + if (Objects.equals(r.getUuid(), UUID_1)) { + // collection.remove(r); + } + } + + Iterator iterator = collection.iterator(); + while (iterator.hasNext()) { + Resume r = iterator.next(); + System.out.println(r); + if (Objects.equals(r.getUuid(), UUID_1)) { + iterator.remove(); + } + } + System.out.println(collection.toString()); + + + Map map = new HashMap<>(); + map.put(UUID_1, RESUME_1); + map.put(UUID_2, RESUME_2); + map.put(UUID_3, RESUME_3); + + // Bad! + for (String uuid : map.keySet()) { + System.out.println(map.get(uuid)); + } + + for (Map.Entry entry : map.entrySet()) { + System.out.println(entry.getValue()); + } +} + + static void printAll() { + System.out.println("\nGet All"); + for (Resume r : ABSTRACT_STORAGE.getAll()) { + System.out.println(r); + } + } +} + + diff --git a/src/com/urise/webapp/MainReflection.java b/src/com/urise/webapp/MainReflection.java new file mode 100644 index 00000000..a6066412 --- /dev/null +++ b/src/com/urise/webapp/MainReflection.java @@ -0,0 +1,23 @@ +package com.urise.webapp; + +import com.urise.webapp.model.Resume; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class MainReflection { + public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + Resume r = new Resume(); + Class resumeClass = r.getClass(); + Field field = resumeClass.getDeclaredFields()[0]; + field.setAccessible(true); + System.out.println(field.getName()); + System.out.println(field.get(r)); + field.set(r, "new_uuid"); + System.out.println(r); + Method method = resumeClass.getMethod("toString"); + Object result = method.invoke(r); + System.out.println(result); + } +} diff --git a/src/com/urise/webapp/MainTestArrayStorage.java b/src/com/urise/webapp/MainTestArrayStorage.java new file mode 100644 index 00000000..d5a63d72 --- /dev/null +++ b/src/com/urise/webapp/MainTestArrayStorage.java @@ -0,0 +1,48 @@ +package com.urise.webapp; + +import com.urise.webapp.model.Resume; +import com.urise.webapp.storage.AbstractArrayStorage; +import com.urise.webapp.storage.ArrayStorage; + +/** + * Test for your com.urise.webapp.storage.ArrayStorage implementation + */ +public class MainTestArrayStorage { + private static final AbstractArrayStorage ARRAY_STORAGE = new ArrayStorage(); +// private static final AbstractArrayStorage ARRAY_STORAGE = new SortedArrayStorage(); + + public static void main(String[] args) { + Resume r1 = new Resume("uuid4"); + Resume r2 = new Resume("uuid2"); + Resume r3 = new Resume("uuid1"); + ARRAY_STORAGE.save(r1); + ARRAY_STORAGE.save(r2); + ARRAY_STORAGE.save(r3); + printAll(); + + System.out.println("Get r1: " + ARRAY_STORAGE.get(r1.getUuid())); + System.out.println("Size: " + ARRAY_STORAGE.size()); + +// System.out.println("Get dummy: " + ARRAY_STORAGE.get("dummy")); + + Resume r = new Resume("uuid2"); + ARRAY_STORAGE.update(r); + ARRAY_STORAGE.save(new Resume("dummy")); + + printAll(); + ARRAY_STORAGE.delete(r2.getUuid()); + printAll(); + ARRAY_STORAGE.clear(); + printAll(); + + System.out.println("Size: " + ARRAY_STORAGE.size()); + ARRAY_STORAGE.size(); + } + + static void printAll() { + System.out.println("\nGet All"); + for (Resume r : ARRAY_STORAGE.getAll()) { + System.out.println(r); + } + } +} \ No newline at end of file diff --git a/src/com/urise/webapp/exception/ExistStorageException.java b/src/com/urise/webapp/exception/ExistStorageException.java new file mode 100644 index 00000000..73fbbf8f --- /dev/null +++ b/src/com/urise/webapp/exception/ExistStorageException.java @@ -0,0 +1,7 @@ +package com.urise.webapp.exception; + +public class ExistStorageException extends StorageException { + public ExistStorageException(String uuid) { + super("Resume " + uuid + " already exist", uuid); + } +} diff --git a/src/com/urise/webapp/exception/NotExistStorageException.java b/src/com/urise/webapp/exception/NotExistStorageException.java new file mode 100644 index 00000000..68164920 --- /dev/null +++ b/src/com/urise/webapp/exception/NotExistStorageException.java @@ -0,0 +1,7 @@ +package com.urise.webapp.exception; + +public class NotExistStorageException extends StorageException { + public NotExistStorageException(String uuid) { + super("Resume " + uuid + " not exist", uuid); + } +} diff --git a/src/com/urise/webapp/exception/StorageException.java b/src/com/urise/webapp/exception/StorageException.java new file mode 100644 index 00000000..d6bfa9ed --- /dev/null +++ b/src/com/urise/webapp/exception/StorageException.java @@ -0,0 +1,14 @@ +package com.urise.webapp.exception; + +public class StorageException extends RuntimeException { + private final String uuid; + + public StorageException(String message, String uuid) { + super(message); + this.uuid = uuid; + } + + public String getUuid() { + return uuid; + } +} diff --git a/src/com/urise/webapp/model/Resume.java b/src/com/urise/webapp/model/Resume.java new file mode 100644 index 00000000..1a2176d2 --- /dev/null +++ b/src/com/urise/webapp/model/Resume.java @@ -0,0 +1,46 @@ +package com.urise.webapp.model; + +import java.util.Objects; +import java.util.UUID; + +/** + * Initial resume class + */ +public class Resume implements Comparable { + private final String uuid; + + public Resume() { + this(UUID.randomUUID().toString()); + } + + public Resume(String uuid) { + this.uuid = uuid; + } + + public String getUuid() { + return uuid; + } + + @Override + public String toString() { + return uuid; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Resume resume = (Resume) o; + return Objects.equals(uuid, resume.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(uuid); + } + + @Override + public int compareTo(Resume o) { + return uuid.compareTo(o.uuid); + } +} \ No newline at end of file diff --git a/src/com/urise/webapp/storage/AbstractArrayStorage.java b/src/com/urise/webapp/storage/AbstractArrayStorage.java new file mode 100644 index 00000000..83d9cc6d --- /dev/null +++ b/src/com/urise/webapp/storage/AbstractArrayStorage.java @@ -0,0 +1,67 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.exception.NotExistStorageException; +import com.urise.webapp.exception.StorageException; +import com.urise.webapp.model.Resume; + +import java.util.Arrays; + +/** + * Array based storage for Resumes + */ +public abstract class AbstractArrayStorage extends AbstractStorage { + protected static final int STORAGE_LIMIT = 10000; + protected final Resume[] storage = new Resume[STORAGE_LIMIT]; + protected int size = 0; + + public void clear() { + Arrays.fill(storage, 0, size, null); + size = 0; + System.out.println("\nThe " + storage.getClass().getSimpleName() + " was successfully cleared"); + } + + public final void doUpdate(Resume r, Object searchKey) { + storage[(Integer) searchKey] = r; + System.out.println("\nElement " + r + " successfully update"); + } + + public final void doSave(Object searchKey, Resume r) { + if (size == STORAGE_LIMIT) { + throw new StorageException("Storage overflow", r.getUuid()); + } + insertResume(r); + size++; + System.out.println("Element " + r + " successfully saved to storage."); + } + + public final Resume doGet(Object searchKey) { + return storage[(Integer) searchKey]; + } + + public final void doDelete(String uuid) { + Object searchKey = getSearchKey(uuid); + if (!isExisting(searchKey)) { + throw new NotExistStorageException(uuid); + } + fillDeletedElement((Integer) searchKey); + storage[size - 1] = null; + size--; + System.out.println("\nElement " + uuid + " successfully deleted from storage"); + } + + public Resume[] getAll() { + return Arrays.copyOf(storage, size); + } + + public int size() { + return size; + } + + protected abstract void insertResume(Resume r); + + protected abstract void fillDeletedElement(int index); + + protected abstract Object getSearchKey(String uuid); + + protected abstract boolean isExisting(Object searchKey); +} \ No newline at end of file diff --git a/src/com/urise/webapp/storage/AbstractStorage.java b/src/com/urise/webapp/storage/AbstractStorage.java new file mode 100644 index 00000000..259d08c2 --- /dev/null +++ b/src/com/urise/webapp/storage/AbstractStorage.java @@ -0,0 +1,73 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.exception.ExistStorageException; +import com.urise.webapp.exception.NotExistStorageException; +import com.urise.webapp.model.Resume; + +public abstract class AbstractStorage implements Storage { + + @Override + public void update(Resume r) { + Object searchKey = getExistingSearchKey(r.getUuid()); + if (!isExisting(searchKey)) { + throw new NotExistStorageException(r.getUuid()); + } + doUpdate(r, searchKey); + } + + @Override + public void save(Resume r) { + Object searchKey = getNotExistingSearchKey(r.getUuid()); + doSave(searchKey, r); + } + + @Override + public Resume get(String uuid) { + Object searchKey = getExistingSearchKey(uuid); + return doGet(searchKey); + } + + @Override + public void delete(String uuid) { + getExistingSearchKey(uuid); + doDelete(uuid); + } + + protected Object getExistingSearchKey(String uuid) { + if (uuid == null) { + throw new IllegalArgumentException("Resume must not be null"); + } + Object searchKey = getSearchKey(uuid); + if (!isExisting(searchKey)) { + throw new NotExistStorageException(uuid); + } + return searchKey; + } + + protected Object getNotExistingSearchKey(String uuid) { + if (uuid == null) { + throw new IllegalArgumentException("Resume must not be null"); + } + Object searchKey = getSearchKey(uuid); + if (isExisting(searchKey)) { + if (searchKey.equals(uuid)) { + throw new IllegalArgumentException("Resume already exists: " + uuid); + } + throw new ExistStorageException(uuid); + } + return searchKey; + } + + protected abstract boolean isExisting(Object searchKey); + + protected abstract void doUpdate(Resume r, Object searchKey); + + protected abstract void doSave(Object searchKey, Resume r); + + protected abstract Resume doGet(Object searchKey); + + protected abstract void doDelete(String uuid); + + protected abstract Object getSearchKey(String uuid); +} + diff --git a/src/com/urise/webapp/storage/ArrayStorage.java b/src/com/urise/webapp/storage/ArrayStorage.java new file mode 100644 index 00000000..aa2601fd --- /dev/null +++ b/src/com/urise/webapp/storage/ArrayStorage.java @@ -0,0 +1,34 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.model.Resume; + +/** + * Array based storage for Resumes + */ +public class ArrayStorage extends AbstractArrayStorage { + + @Override + protected Object getSearchKey(String uuid) { + for (int i = 0; i < size; i++) { + if (storage[i].getUuid().equals(uuid)) { + return i; + } + } + return -1; + } + + @Override + protected void insertResume(Resume r) { + storage[size] = r; + } + + @Override + protected void fillDeletedElement(int index) { + storage[index] = storage[size - 1]; + } + + @Override + protected boolean isExisting(Object searchKey) { + return searchKey instanceof Integer && (Integer) searchKey >= 0; + } +} \ No newline at end of file diff --git a/src/com/urise/webapp/storage/ListStorage.java b/src/com/urise/webapp/storage/ListStorage.java new file mode 100644 index 00000000..937b2814 --- /dev/null +++ b/src/com/urise/webapp/storage/ListStorage.java @@ -0,0 +1,71 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.exception.ExistStorageException; +import com.urise.webapp.exception.NotExistStorageException; +import com.urise.webapp.model.Resume; + +import java.util.ArrayList; +import java.util.List; + +public class ListStorage extends AbstractStorage { + protected List storage = new ArrayList<>(); + + @Override + public void clear() { + storage.clear(); + } + + + @Override + protected boolean isExisting(Object searchKey) { + return searchKey != null && (Integer) searchKey >= 0; + } + + @Override + public void doUpdate(Resume r, Object searchKey) { + Resume resume = get(r.getUuid()); + storage.set(storage.indexOf(resume), r); + } + + @Override + public void doSave(Object searchKey, Resume r) { + if (storage.contains(r)) { + throw new ExistStorageException(r.getUuid()); + } + storage.add(r); + } + + @Override + public Resume doGet(Object searchKey) { + int index = (Integer) searchKey; + if (index >= 0 && index < storage.size()) { + return storage.get(index); + } + throw new NotExistStorageException((String) searchKey); + } + + @Override + public void doDelete(String uuid) { + Resume resume = get(uuid); + storage.remove(resume); + } + + @Override + protected Integer getSearchKey(String uuid) { + for (int i = 0; i < storage.size(); i++) + if (storage.get(i).getUuid().equals(uuid)) { + return i; + } + return -1; + } + + @Override + public Resume[] getAll() { + return storage.toArray(new Resume[0]); + } + + @Override + public int size() { + return storage.size(); + } +} diff --git a/src/com/urise/webapp/storage/MapStorage.java b/src/com/urise/webapp/storage/MapStorage.java new file mode 100644 index 00000000..b9f03b6d --- /dev/null +++ b/src/com/urise/webapp/storage/MapStorage.java @@ -0,0 +1,58 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.model.Resume; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class MapStorage extends AbstractStorage { + private final Map storage = new LinkedHashMap<>(); + + @Override + protected boolean isExisting(Object searchKey) { + return searchKey != null && storage.containsKey(searchKey); + } + + @Override + protected void doUpdate(Resume r, Object searchKey) { + storage.put(r.getUuid(), r); + } + + @Override + protected void doSave(Object searchKey, Resume r) { + if (searchKey != null) { + throw new IllegalArgumentException(r.getUuid()); + } + storage.put(r.getUuid(), r); + } + + @Override + protected Resume doGet(Object searchKey) { + return storage.get(searchKey); + } + + @Override + protected void doDelete(String uuid) { + storage.remove(uuid); + } + + @Override + protected String getSearchKey(String uuid) { + return storage.containsKey(uuid) ? uuid : null; + } + + @Override + public void clear() { + storage.clear(); + } + + @Override + public Resume[] getAll() { + return storage.values().toArray(new Resume[0]); + } + + @Override + public int size() { + return storage.size(); + } +} diff --git a/src/com/urise/webapp/storage/SortedArrayStorage.java b/src/com/urise/webapp/storage/SortedArrayStorage.java new file mode 100644 index 00000000..5fc45e14 --- /dev/null +++ b/src/com/urise/webapp/storage/SortedArrayStorage.java @@ -0,0 +1,31 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.model.Resume; + +import java.util.Arrays; + +public class SortedArrayStorage extends AbstractArrayStorage { + + @Override + protected Object getSearchKey(String uuid) { + Resume searchKey = new Resume(uuid); + return Arrays.binarySearch(storage, 0, size, searchKey); + } + + @Override + protected void insertResume(Resume r) { + int insertIndex = -(Arrays.binarySearch(storage, 0, size, r) + 1); + System.arraycopy(storage, insertIndex, storage, insertIndex + 1, size - insertIndex); + storage[insertIndex] = r; + } + + @Override + protected void fillDeletedElement(int index) { + System.arraycopy(storage, index + 1, storage, index, size - index - 1); + } + + @Override + protected boolean isExisting(Object searchKey) { + return searchKey instanceof Integer && (Integer) searchKey >= 0; + } +} diff --git a/src/com/urise/webapp/storage/Storage.java b/src/com/urise/webapp/storage/Storage.java new file mode 100644 index 00000000..fef5ceed --- /dev/null +++ b/src/com/urise/webapp/storage/Storage.java @@ -0,0 +1,26 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.model.Resume; + +/** + * Array based storage for Resumes + */ +public interface Storage { + void clear(); + + void update(Resume r); + + void save(Resume r); + + Resume get(String uuid); + + void delete(String uuid); + + /** + * @return array, contains only Resumes in storage (without null) + */ + Resume[] getAll(); + + int size(); +} + diff --git a/test/com/urise/webapp/storage/AbstractArrayStorageTest.java b/test/com/urise/webapp/storage/AbstractArrayStorageTest.java new file mode 100644 index 00000000..48d2470e --- /dev/null +++ b/test/com/urise/webapp/storage/AbstractArrayStorageTest.java @@ -0,0 +1,138 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.exception.ExistStorageException; +import com.urise.webapp.exception.NotExistStorageException; +import com.urise.webapp.exception.StorageException; +import com.urise.webapp.model.Resume; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +public abstract class AbstractArrayStorageTest { + + private final Storage storage; + + private static final String UUID_1 = "uuid1"; + private static final String UUID_2 = "uuid2"; + private static final String UUID_3 = "uuid3"; + private static final String UUID_4 = "uuid4"; + + private static final Resume RESUME_1; + private static final Resume RESUME_2; + private static final Resume RESUME_3; + private static final Resume SAVE_RESUME; + + static { + RESUME_1 = new Resume(UUID_1); + RESUME_2 = new Resume(UUID_2); + RESUME_3 = new Resume(UUID_3); + SAVE_RESUME = new Resume(UUID_4); + } + + private final Resume UUID_NOT_EXIST = new Resume("dummy"); + + private final int size = 3; + + protected AbstractArrayStorageTest(Storage storage) { + this.storage = storage; + } + + @Before + public void setUp() { + storage.clear(); + storage.save(RESUME_1); + storage.save(RESUME_2); + storage.save(RESUME_3); + } + + @Test + public void clear() { + storage.clear(); + assertSize(0); + Assert.assertArrayEquals(new Resume[0], storage.getAll()); + } + + @Test + public void update() { + storage.update(RESUME_2); + Assert.assertSame(RESUME_2, storage.get(UUID_2)); + } + + @Test(expected = NotExistStorageException.class) + public void updateNotExist() { + storage.update(UUID_NOT_EXIST); + } + + @Test + public void save() { + storage.save(SAVE_RESUME); + assertGet(SAVE_RESUME); + assertSize(size + 1); + } + + @Test + public void saveExist() { + assertThrows(ExistStorageException.class, () -> storage.save(RESUME_2)); + } + + @Test + public void get() { + assertGet(RESUME_1); + } + + public void assertGet(Resume resume) { + Assert.assertEquals(resume, storage.get(resume.getUuid())); + } + + @Test(expected = NotExistStorageException.class) + public void getNotExist() { + storage.get(UUID_NOT_EXIST.getUuid()); + } + + @Test + public void delete() { + storage.delete(UUID_2); + assertSize(size - 1); + assertThrows(NotExistStorageException.class, () -> storage.get(UUID_2)); + } + + @Test + public void deleteNotExist() { + assertThrows(NotExistStorageException.class, () -> storage.delete(UUID_NOT_EXIST.getUuid())); + } + + @Test + public void getAll() { + Resume[] array = storage.getAll(); + Assert.assertEquals(size, array.length); + assertEquals(RESUME_1, array[0]); + assertEquals(RESUME_2, array[1]); + assertEquals(RESUME_3, array[2]); + } + + @Test + public void size() { + assertSize(size); + } + + private void assertSize(int expectedSize) { + Assert.assertEquals(expectedSize, storage.size()); + } + + + @Test + public void testStorageOverflow() { + storage.clear(); + try { + for (int i = 0; i < AbstractArrayStorage.STORAGE_LIMIT; i++) { + storage.save(new Resume()); + } + } catch (StorageException e) { + Assert.fail("Переполнение произошло раньше времени: " + e.getMessage()); + } + assertThrows(StorageException.class, () -> storage.save(SAVE_RESUME)); + } +} diff --git a/test/com/urise/webapp/storage/ArrayStorageTest.java b/test/com/urise/webapp/storage/ArrayStorageTest.java new file mode 100644 index 00000000..4af5bf08 --- /dev/null +++ b/test/com/urise/webapp/storage/ArrayStorageTest.java @@ -0,0 +1,7 @@ +package com.urise.webapp.storage; + +public class ArrayStorageTest extends AbstractArrayStorageTest { + public ArrayStorageTest() { + super(new ArrayStorage()); + } +} \ No newline at end of file diff --git a/test/com/urise/webapp/storage/ListStorageTest.java b/test/com/urise/webapp/storage/ListStorageTest.java new file mode 100644 index 00000000..3ead1ae3 --- /dev/null +++ b/test/com/urise/webapp/storage/ListStorageTest.java @@ -0,0 +1,120 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.exception.ExistStorageException; +import com.urise.webapp.exception.NotExistStorageException; +import com.urise.webapp.model.Resume; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +public class ListStorageTest { + private ListStorage listStorage; + + private static final String UUID_1 = "uuid1"; + private static final String UUID_2 = "uuid2"; + private static final String UUID_3 = "uuid3"; + private static final String UUID_4 = "uuid4"; + + private static final Resume RESUME_1; + private static final Resume RESUME_2; + private static final Resume RESUME_3; + private static final Resume SAVE_RESUME; + + static { + RESUME_1 = new Resume(UUID_1); + RESUME_2 = new Resume(UUID_2); + RESUME_3 = new Resume(UUID_3); + SAVE_RESUME = new Resume(UUID_4); + } + + private final Resume UUID_NOT_EXIST = new Resume("dummy"); + + private final int size = 3; + + @Before + public void setUp() { + listStorage = new ListStorage(); + listStorage.clear(); + listStorage.save(RESUME_1); + listStorage.save(RESUME_2); + listStorage.save(RESUME_3); + } + + @Test + public void clear() { + listStorage.clear(); + assertSize(0); + Assert.assertArrayEquals(new Resume[0], listStorage.getAll()); + } + + @Test + public void update() { + listStorage.update(RESUME_2); + Assert.assertSame(RESUME_2, listStorage.get(UUID_2)); + } + + @Test(expected = NotExistStorageException.class) + public void updateNotExist() { + listStorage.update(UUID_NOT_EXIST); + } + + @Test + public void save() { + listStorage.save(SAVE_RESUME); + assertGet(SAVE_RESUME); + assertSize(size + 1); + } + + @Test + public void saveExist() { + assertThrows(ExistStorageException.class, () -> listStorage.save(RESUME_1)); + } + + @Test + public void get() { + assertGet(RESUME_1); + } + + private void assertGet(Resume resume) { + assertEquals(resume, listStorage.get(resume.getUuid())); + } + + @Test(expected = NotExistStorageException.class) + public void getNotExist() { + listStorage.get(UUID_NOT_EXIST.getUuid()); + } + + @Test + public void delete() { + listStorage.delete(UUID_2); + assertSize(size - 1); + assertThrows(NotExistStorageException.class, () -> listStorage.get(UUID_2)); + } + + @Test + public void deleteNotExist() { + assertThrows(NotExistStorageException.class, () -> listStorage.delete(UUID_NOT_EXIST.getUuid())); + } + + @Test + public void getAll() { + Resume[] array = listStorage.getAll(); + assertEquals(size, array.length); + assertEquals(RESUME_1, array[0]); + assertEquals(RESUME_2, array[1]); + assertEquals(RESUME_3, array[2]); + } + + @Test + public void size() { + assertSize(size); + } + + private void assertSize(int expectedSize) { + assertEquals(expectedSize, listStorage.size()); + } +} + diff --git a/test/com/urise/webapp/storage/MapStorageTest.java b/test/com/urise/webapp/storage/MapStorageTest.java new file mode 100644 index 00000000..03a70df5 --- /dev/null +++ b/test/com/urise/webapp/storage/MapStorageTest.java @@ -0,0 +1,117 @@ +package com.urise.webapp.storage; + +import com.urise.webapp.exception.NotExistStorageException; +import com.urise.webapp.model.Resume; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +public class MapStorageTest { + + private MapStorage mapStorage; + + private static final String UUID_1 = "uuid1"; + private static final String UUID_2 = "uuid2"; + private static final String UUID_3 = "uuid3"; + private static final String UUID_4 = "uuid4"; + + private static final Resume RESUME_1; + private static final Resume RESUME_2; + private static final Resume RESUME_3; + private static final Resume SAVE_RESUME; + + static { + RESUME_1 = new Resume(UUID_1); + RESUME_2 = new Resume(UUID_2); + RESUME_3 = new Resume(UUID_3); + SAVE_RESUME = new Resume(UUID_4); + } + + private final Resume UUID_NOT_EXIST = new Resume("dummy"); + + private final int size = 3; + + @Before + public void setUp() { + mapStorage = new MapStorage(); + mapStorage.clear(); + mapStorage.save(RESUME_1); + mapStorage.save(RESUME_2); + mapStorage.save(RESUME_3); + } + + @Test + public void clear() { + mapStorage.clear(); + assertSize(0); + Assert.assertArrayEquals(new Resume[0], mapStorage.getAll()); + } + + @Test + public void update() { + mapStorage.update(RESUME_2); + Assert.assertSame(RESUME_2, mapStorage.get(UUID_2)); + } + + @Test(expected = NotExistStorageException.class) + public void updateNotExist() { + mapStorage.update(UUID_NOT_EXIST); + } + + @Test + public void save() { + mapStorage.save(SAVE_RESUME); + assertGet(SAVE_RESUME); + assertSize(size + 1); + } + + @Test + public void saveExist() { + assertThrows(IllegalArgumentException.class, () -> mapStorage.save(RESUME_1)); + } + + @Test + public void get() { + assertGet(RESUME_1); + } + + private void assertGet(Resume resume) { + assertEquals(resume, mapStorage.get(resume.getUuid())); + } + + @Test(expected = NotExistStorageException.class) + public void getNotExist() { + mapStorage.get(UUID_NOT_EXIST.getUuid()); + } + + @Test + public void delete() { + mapStorage.delete(UUID_2); + assertSize(size - 1); + assertThrows(NotExistStorageException.class, () -> mapStorage.get(UUID_2)); + } + + @Test + public void deleteNotExist() { + assertThrows(NotExistStorageException.class, () -> mapStorage.delete(UUID_NOT_EXIST.getUuid())); + } + + @Test + public void getAll() { + Resume[] array = mapStorage.getAll(); + assertEquals(size, array.length); + Assert.assertArrayEquals(new Resume[]{RESUME_1, RESUME_2, RESUME_3}, array); + } + + @Test + public void size() { + assertSize(size); + } + + private void assertSize(int expectedSize) { + assertEquals(expectedSize, mapStorage.size()); + } +} diff --git a/test/com/urise/webapp/storage/SortedArrayStorageTest.java b/test/com/urise/webapp/storage/SortedArrayStorageTest.java new file mode 100644 index 00000000..8bdb1190 --- /dev/null +++ b/test/com/urise/webapp/storage/SortedArrayStorageTest.java @@ -0,0 +1,7 @@ +package com.urise.webapp.storage; + +public class SortedArrayStorageTest extends AbstractArrayStorageTest { + public SortedArrayStorageTest() { + super(new SortedArrayStorage()); + } +} \ No newline at end of file