diff --git a/.gitignore b/.gitignore index 188fae8..ba9ea56 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,4 @@ out *.iml log - - - +lib diff --git a/src/ArrayStorage.java b/src/ArrayStorage.java deleted file mode 100644 index cefa261..0000000 --- a/src/ArrayStorage.java +++ /dev/null @@ -1,85 +0,0 @@ -import java.util.Arrays; -import java.util.Objects; - -/** - * Array based storage for Resumes - */ -public class ArrayStorage { - private Resume[] storage = new Resume[10_000]; - - private int size; - - public void clear() { - Arrays.fill(storage, 0, size, null); - size = 0; - } - - public void update(Resume resume) { - int index = getIndex(resume.getUuid()); - - if (index >= 0) { - storage[index] = resume; - } else { - System.out.println("ERROR in method 'update' :" + resume.getUuid()); - } - } - - public void save(Resume resume) { - int index = getIndex(resume.getUuid()); - - if (index >= 0) { - System.out.println("ERROR in method 'save' :" + resume.getUuid()); - } else { - if (size < storage.length) { - storage[size] = resume; - size++; - } else { - System.out.println("ERROR in method 'save' :" + resume.getUuid() + " (storage backing array boundary has been reached)"); - } - } - } - - public Resume get(String uuid) { - int index = getIndex(uuid); - - if (index >= 0) { - return storage[index]; - } else { - System.out.println("Invalid uuid in method 'get': " + uuid); - return null; - } - } - - - public void delete(String uuid) { - int index = getIndex(uuid); - - if (index >= 0) { - storage[index] = storage[size - 1]; - storage[size - 1] = null; - size--; - } else { - System.out.println("Invalid uuid in method 'delete': " + uuid); - } - } - - /** - * @return array, contains only Resumes in storage (without null) - */ - public Resume[] getAll() { - return Arrays.copyOf(storage, size); - } - - public int size() { - return size; - } - - private int getIndex(String uuid) { - for (int i = 0; i < size; i++) { - if (Objects.equals(storage[i].getUuid(), uuid)) { - return i; - } - } - return -1; - } -} diff --git a/src/MainTestArrayStorage.java b/src/MainTestArrayStorage.java deleted file mode 100644 index 7683807..0000000 --- a/src/MainTestArrayStorage.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Test for your ArrayStorage implementation - */ -public class MainTestArrayStorage { - static final ArrayStorage ARRAY_STORAGE = new ArrayStorage(); - static int ARRAY_STORAGE_LIMIT = 10_000; - - public static void main(String[] args) { - Resume r1 = new Resume(); - r1.setUuid("uuid1"); - Resume r2 = new Resume(); - r2.setUuid("uuid2"); - Resume r3 = new Resume(); - r3.setUuid("uuid3"); - Resume r2new = new Resume(); - r2new.setUuid("uuid2"); - - ARRAY_STORAGE.save(r1); - ARRAY_STORAGE.save(r2); - ARRAY_STORAGE.save(r3); - - 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")); - - ARRAY_STORAGE.save(r2new); - - ARRAY_STORAGE.update(r2new); - System.out.println("Get r2new: " + ARRAY_STORAGE.get(r2new.getUuid())); - - ARRAY_STORAGE.get("uuid111"); - ARRAY_STORAGE.delete("uuid111"); - - printAll(); - ARRAY_STORAGE.delete(r1.getUuid()); - printAll(); - ARRAY_STORAGE.clear(); - printAll(); - - System.out.println("Size: " + ARRAY_STORAGE.size()); - - for (int i = 0; i <= ARRAY_STORAGE_LIMIT; i++) { - Resume r = new Resume(); - r.setUuid("uuid" + i); - ARRAY_STORAGE.save(r); - } - - 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 ef673e6..0000000 --- a/src/Resume.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Initial resume class - */ -public class Resume { - - // Unique identifier - private String uuid; - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - @Override - public String toString() { - return uuid; - } -} diff --git a/src/MainArray.java b/src/ru/javawebinar/basejava/MainArray.java similarity index 70% rename from src/MainArray.java rename to src/ru/javawebinar/basejava/MainArray.java index cc060cf..6deb931 100644 --- a/src/MainArray.java +++ b/src/ru/javawebinar/basejava/MainArray.java @@ -1,19 +1,25 @@ +package ru.javawebinar.basejava; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.Storage; +import ru.javawebinar.basejava.storage.impl.ArrayStorage; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.List; /** - * Interactive test for ArrayStorage implementation - * (just run, no need to understand) + * Test for ru.javawebinar.basejava.storage.impl.ArrayStorage */ public class MainArray { - private final static ArrayStorage ARRAY_STORAGE = new ArrayStorage(); + private final static Storage ARRAY_STORAGE = new ArrayStorage(); public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - Resume r; + Resume resume; while (true) { - System.out.print("Введите одну из команд - (list | save uuid | update uuid | delete uuid | get uuid | clear | exit): "); + System.out.print("Введите одну из команд - (list | save uuid | delete uuid | get uuid | update uuid | clear | exit): "); String[] params = reader.readLine().trim().toLowerCase().split(" "); if (params.length < 1 || params.length > 2) { System.out.println("Неверная команда."); @@ -31,15 +37,14 @@ public static void main(String[] args) throws IOException { System.out.println(ARRAY_STORAGE.size()); break; case "save": - r = new Resume(); - r.setUuid(uuid); - ARRAY_STORAGE.save(r); + resume = new Resume(uuid, "Name" + uuid); + ARRAY_STORAGE.save(resume); printAll(); break; case "update": - Resume rNew = new Resume(); - rNew.setUuid(uuid); - ARRAY_STORAGE.update(rNew); + resume = new Resume(uuid, "Name" + uuid); + ARRAY_STORAGE.update(resume); + printAll(); break; case "delete": ARRAY_STORAGE.delete(uuid); @@ -62,13 +67,13 @@ public static void main(String[] args) throws IOException { } static void printAll() { - Resume[] all = ARRAY_STORAGE.getAll(); + List all = ARRAY_STORAGE.getAllSorted(); System.out.println("----------------------------"); - if (all.length == 0) { + if (all.size() == 0) { System.out.println("Empty"); } else { - for (Resume r : all) { - System.out.println(r); + for (Resume resume : all) { + System.out.println(resume); } } System.out.println("----------------------------"); diff --git a/src/ru/javawebinar/basejava/MainCollections.java b/src/ru/javawebinar/basejava/MainCollections.java new file mode 100644 index 0000000..bff3f7c --- /dev/null +++ b/src/ru/javawebinar/basejava/MainCollections.java @@ -0,0 +1,58 @@ +package ru.javawebinar.basejava; + +import ru.javawebinar.basejava.model.Resume; + +import java.util.*; + +public class MainCollections { + private static final String UUID_1 = "uuid1"; + private static final Resume RESUME_1 = new Resume(UUID_1, "Name1"); + + private static final String UUID_2 = "uuid2"; + private static final Resume RESUME_2 = new Resume(UUID_2, "Name2"); + + private static final String UUID_3 = "uuid3"; + private static final Resume RESUME_3 = new Resume(UUID_3, "Name3"); + + private static final String UUID_4 = "uuid4"; + private static final Resume RESUME_4 = new Resume(UUID_4, "Name4"); + + public static void main(String[] args) { + 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()); + } + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/MainReflection.java b/src/ru/javawebinar/basejava/MainReflection.java new file mode 100644 index 0000000..387bdba --- /dev/null +++ b/src/ru/javawebinar/basejava/MainReflection.java @@ -0,0 +1,29 @@ +package ru.javawebinar.basejava; + +import ru.javawebinar.basejava.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 resume = new Resume("New Person"); + Field field = resume.getClass().getDeclaredFields()[0]; + field.setAccessible(true); + System.out.println(field.getName()); + System.out.println(field.get(resume)); + field.set(resume, "new_uuid"); + // TODO : invoke resume.toString via reflection + System.out.println(resume); + + System.out.println(field.get(resume)); + + Method toString = resume.getClass().getMethod("toString"); + + Object invoke = toString.invoke(resume); + System.out.println(invoke); + + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/MainString.java b/src/ru/javawebinar/basejava/MainString.java new file mode 100644 index 0000000..681b189 --- /dev/null +++ b/src/ru/javawebinar/basejava/MainString.java @@ -0,0 +1,18 @@ +package ru.javawebinar.basejava; + +public class MainString { + public static void main(String[] args) { + String[] strArray = new String[]{"1", "2", "3", "4", "5"}; +// String result = ""; + StringBuilder sb = new StringBuilder(); + for (String str : strArray) { + sb.append(str).append(", "); + } + System.out.println(sb.toString()); + + String str1 = "abc"; + String str3 = "c"; + String str2 = ("ab" + str3).intern(); + System.out.println(str1 == str2); + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/MainTestArrayStorage.java b/src/ru/javawebinar/basejava/MainTestArrayStorage.java new file mode 100644 index 0000000..d4ff5b8 --- /dev/null +++ b/src/ru/javawebinar/basejava/MainTestArrayStorage.java @@ -0,0 +1,42 @@ +package ru.javawebinar.basejava; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.impl.ArrayStorage; + + +/** + * Test ru.javawebinar.basejava.storage.impl.ArrayStorage + */ +public class MainTestArrayStorage { + static final ArrayStorage ARRAY_STORAGE = new ArrayStorage(); + + public static void main(String[] args) { + Resume r1 = new Resume("uuid1", "Name1"); + Resume r2 = new Resume("uuid2", "Name2"); + Resume r3 = new Resume("uuid3", "Name3"); + + ARRAY_STORAGE.save(r1); + ARRAY_STORAGE.save(r2); + ARRAY_STORAGE.save(r3); + + 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")); + + printAll(); + ARRAY_STORAGE.delete(r1.getUuid()); + 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.getAllSorted()) { + System.out.println(r); + } + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/exception/ExistStorageException.java b/src/ru/javawebinar/basejava/exception/ExistStorageException.java new file mode 100644 index 0000000..33d98be --- /dev/null +++ b/src/ru/javawebinar/basejava/exception/ExistStorageException.java @@ -0,0 +1,7 @@ +package ru.javawebinar.basejava.exception; + +public class ExistStorageException extends StorageException { + public ExistStorageException(String uuid) { + super("Resume " + uuid + " already exist", uuid); + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/exception/NotExistStorageException.java b/src/ru/javawebinar/basejava/exception/NotExistStorageException.java new file mode 100644 index 0000000..9a9b867 --- /dev/null +++ b/src/ru/javawebinar/basejava/exception/NotExistStorageException.java @@ -0,0 +1,7 @@ +package ru.javawebinar.basejava.exception; + +public class NotExistStorageException extends StorageException { + public NotExistStorageException(String uuid) { + super("Resume " + uuid + " not exist", uuid); + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/exception/StorageException.java b/src/ru/javawebinar/basejava/exception/StorageException.java new file mode 100644 index 0000000..dbd1be0 --- /dev/null +++ b/src/ru/javawebinar/basejava/exception/StorageException.java @@ -0,0 +1,14 @@ +package ru.javawebinar.basejava.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; + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/model/Resume.java b/src/ru/javawebinar/basejava/model/Resume.java new file mode 100644 index 0000000..86c602b --- /dev/null +++ b/src/ru/javawebinar/basejava/model/Resume.java @@ -0,0 +1,61 @@ +package ru.javawebinar.basejava.model; + +import java.util.Objects; +import java.util.UUID; + +/** + * ru.javawebinar.basejava.model.Resume class + */ +public class Resume implements Comparable { + + // Unique identifier + private String uuid; + + private String fullName; + + public Resume() { + } + + ; + + public Resume(String fullName) { + this(UUID.randomUUID().toString(), fullName); + } + + + public Resume(String uuid, String fullName) { + this.uuid = uuid; + this.fullName = fullName; + } + + 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 uuid.equals(resume.uuid) && + fullName.equals(resume.fullName); + } + + @Override + public int hashCode() { + return Objects.hash(uuid, fullName); + } + + @Override + public int compareTo(Resume o) { + int candidate = fullName.compareTo(o.fullName); + if (candidate != 0) return candidate; + else return uuid.compareTo(o.uuid); + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java b/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java new file mode 100644 index 0000000..67ee870 --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java @@ -0,0 +1,67 @@ +package ru.javawebinar.basejava.storage; + +import ru.javawebinar.basejava.exception.StorageException; +import ru.javawebinar.basejava.model.Resume; + +import java.util.Arrays; +import java.util.List; + +/** + * Array based storage for Resumes + */ +public abstract class AbstractArrayStorage extends AbstractStorage { + protected static final int STORAGE_LIMIT = 10_000; + + protected Resume[] storage = new Resume[STORAGE_LIMIT]; + protected int size = 0; + + public int size() { + return size; + } + + public void clear() { + Arrays.fill(storage, 0, size, null); + size = 0; + } + + @Override + protected void doUpdate(Resume resume, Object index) { + storage[(Integer) index] = resume; + } + + @Override + public List doCopyAll() { + return Arrays.asList(Arrays.copyOfRange(storage, 0, size)); + } + + @Override + protected void doSave(Resume resume, Object index) { + if (size == STORAGE_LIMIT) { + throw new StorageException("Storage overflow", resume.getUuid()); + } else { + insertElement(resume, (Integer) index); + size++; + } + } + + @Override + public void doDelete(Object index) { + fillDeletedElement((Integer) index); + storage[size - 1] = null; + size--; + } + + public Resume doGet(Object index) { + return storage[(Integer) index]; + } + + @Override + protected boolean isExist(Object index) { + return (Integer) index >= 0; + } + + protected abstract void fillDeletedElement(int index); + + protected abstract void insertElement(Resume resume, int index); + +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/AbstractStorage.java b/src/ru/javawebinar/basejava/storage/AbstractStorage.java new file mode 100644 index 0000000..3b78f9c --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/AbstractStorage.java @@ -0,0 +1,72 @@ +package ru.javawebinar.basejava.storage; + +import ru.javawebinar.basejava.exception.ExistStorageException; +import ru.javawebinar.basejava.exception.NotExistStorageException; +import ru.javawebinar.basejava.model.Resume; + +import java.util.Collections; +import java.util.List; + +public abstract class AbstractStorage implements Storage { + + protected abstract Object getSearchKey(String uuid); + + protected abstract void doUpdate(Resume r, Object searchKey); + + protected abstract boolean isExist(Object searchKey); + + protected abstract void doSave(Resume r, Object searchKey); + + protected abstract Resume doGet(Object searchKey); + + protected abstract void doDelete(Object searchKey); + + protected abstract List doCopyAll(); + + @Override + public void update(Resume resume) { + Object searchKey = getExistedSearchKey(resume.getUuid()); + doUpdate(resume, searchKey); + } + + @Override + public void save(Resume resume) { + Object searchKey = getNotExistedSearchKey(resume.getUuid()); + doSave(resume, searchKey); + } + + @Override + public void delete(String uuid) { + Object searchKey = getExistedSearchKey(uuid); + doDelete(searchKey); + } + + @Override + public Resume get(String uuid) { + Object searchKey = getExistedSearchKey(uuid); + return doGet(searchKey); + } + + @Override + public List getAllSorted() { + List list = doCopyAll(); + Collections.sort(list); + return list; + } + + private Object getExistedSearchKey(String uuid) { + Object searchKey = getSearchKey(uuid); + if (!isExist(searchKey)) { + throw new NotExistStorageException(uuid); + } + return searchKey; + } + + private Object getNotExistedSearchKey(String uuid) { + Object searchKey = getSearchKey(uuid); + if (isExist(searchKey)) { + throw new ExistStorageException(uuid); + } + return searchKey; + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/Storage.java b/src/ru/javawebinar/basejava/storage/Storage.java new file mode 100644 index 0000000..a29b66b --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/Storage.java @@ -0,0 +1,22 @@ +package ru.javawebinar.basejava.storage; + +import ru.javawebinar.basejava.model.Resume; + +import java.util.List; + +public interface Storage { + + void clear(); + + void update(Resume resume); + + void save(Resume resume); + + Resume get(String uuid); + + void delete(String uuid); + + int size(); + + List getAllSorted(); +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/impl/ArrayStorage.java b/src/ru/javawebinar/basejava/storage/impl/ArrayStorage.java new file mode 100644 index 0000000..ab33615 --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/impl/ArrayStorage.java @@ -0,0 +1,29 @@ +package ru.javawebinar.basejava.storage.impl; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.AbstractArrayStorage; + +/** + * Array based storage for Resumes + */ +public class ArrayStorage extends AbstractArrayStorage { + + @Override + protected void fillDeletedElement(int index) { + storage[index] = storage[size - 1]; + } + + @Override + protected void insertElement(Resume resume, int index) { + storage[size] = resume; + } + + protected Integer getSearchKey(String uuid) { + for (int i = 0; i < size; i++) { + if (uuid.equals(storage[i].getUuid())) { + return i; + } + } + return -1; + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/impl/ListStorage.java b/src/ru/javawebinar/basejava/storage/impl/ListStorage.java new file mode 100644 index 0000000..fb53659 --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/impl/ListStorage.java @@ -0,0 +1,61 @@ +package ru.javawebinar.basejava.storage.impl; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.AbstractStorage; + +import java.util.ArrayList; +import java.util.List; + +public class ListStorage extends AbstractStorage { + private List list = new ArrayList<>(); + + @Override + protected Integer getSearchKey(String uuid) { + for (int i = 0; i < list.size(); i++) { + if (list.get(i).getUuid().equals(uuid)) { + return i; + } + } + return null; + } + + @Override + protected boolean isExist(Object searchKey) { + return searchKey != null; + } + + @Override + protected void doUpdate(Resume resume, Object searchKey) { + list.set((Integer) searchKey, resume); + } + + @Override + protected void doSave(Resume resume, Object searchKey) { + list.add(resume); + } + + @Override + protected Resume doGet(Object searchKey) { + return list.get((Integer) searchKey); + } + + @Override + protected void doDelete(Object searchKey) { + list.remove(((Integer) searchKey).intValue()); + } + + @Override + public void clear() { + list.clear(); + } + + @Override + public List doCopyAll() { + return new ArrayList<>(list); + } + + @Override + public int size() { + return list.size(); + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/impl/MapResumeStorage.java b/src/ru/javawebinar/basejava/storage/impl/MapResumeStorage.java new file mode 100644 index 0000000..f3cc2a9 --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/impl/MapResumeStorage.java @@ -0,0 +1,62 @@ +package ru.javawebinar.basejava.storage.impl; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.AbstractStorage; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MapResumeStorage extends AbstractStorage { + private Map map = new HashMap<>(); + + @Override + protected Resume getSearchKey(String uuid) { + return map.get(uuid); + } + + @Override + protected void doUpdate(Resume resume, Object searchKey) { + map.put(resume.getUuid(), resume); + } + + @Override + protected boolean isExist(Object searchKey) { + return searchKey != null; + } + + @Override + protected void doSave(Resume resume, Object searchKey) { + map.put(resume.getUuid(), resume); + } + + @Override + protected Resume doGet(Object searchKey) { + return (Resume) searchKey; + } + + @Override + protected void doDelete(Object searchKey) { + map.remove(getUuid(searchKey)); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public List doCopyAll() { + return new ArrayList<>(map.values()); + } + + private String getUuid(Object searchKey) { + return ((Resume) searchKey).getUuid(); + } +} diff --git a/src/ru/javawebinar/basejava/storage/impl/MapUuidStorage.java b/src/ru/javawebinar/basejava/storage/impl/MapUuidStorage.java new file mode 100644 index 0000000..93142af --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/impl/MapUuidStorage.java @@ -0,0 +1,59 @@ +package ru.javawebinar.basejava.storage.impl; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.AbstractStorage; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MapUuidStorage extends AbstractStorage { + private Map map = new HashMap<>(); + + @Override + protected String getSearchKey(String uuid) { + return uuid; + } + + @Override + protected void doUpdate(Resume resume, Object searchKey) { + map.put((String) searchKey, resume); + } + + @Override + protected boolean isExist(Object searchKey) { + return map.containsKey(searchKey); + } + + @Override + protected void doSave(Resume resume, Object searchKey) { + map.put((String) searchKey, resume); + } + + @Override + protected Resume doGet(Object searchKey) { + return map.get(searchKey); + } + + @Override + protected void doDelete(Object searchKey) { + map.remove(searchKey); + } + + @Override + public void clear() { + map.clear(); + } + + + @Override + public List doCopyAll() { + return new ArrayList<>(map.values()); + } + + @Override + public int size() { + return map.size(); + } +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/impl/SortedArrayStorage.java b/src/ru/javawebinar/basejava/storage/impl/SortedArrayStorage.java new file mode 100644 index 0000000..2ad9106 --- /dev/null +++ b/src/ru/javawebinar/basejava/storage/impl/SortedArrayStorage.java @@ -0,0 +1,42 @@ +package ru.javawebinar.basejava.storage.impl; + +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.AbstractArrayStorage; + +import java.util.Arrays; +import java.util.Comparator; + +public class SortedArrayStorage extends AbstractArrayStorage { +/* + private static class ResumeComparator implements Comparator { + @Override + public int compare(Resume o1, Resume o2) { + return o1.getUuid().compareTo(o2.getUuid()); + } + } +*/ + + private static final Comparator RESUME_COMPARATOR = Comparator.comparing(Resume::getUuid); + + @Override + protected void fillDeletedElement(int index) { + int numMoved = size - index - 1; + if (numMoved > 0) { + System.arraycopy(storage, index + 1, storage, index, numMoved); + } + } + + @Override + protected void insertElement(Resume resume, int index) { +// http://codereview.stackexchange.com/questions/36221/binary-search-for-inserting-in-array#answer-36239 + int insertIdx = -index - 1; + System.arraycopy(storage, insertIdx, storage, insertIdx + 1, size - insertIdx); + storage[insertIdx] = resume; + } + + @Override + protected Integer getSearchKey(String uuid) { + Resume searchKey = new Resume(uuid, "DummyName"); + return Arrays.binarySearch(storage, 0, size, searchKey, RESUME_COMPARATOR); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/Util.java b/test/ru/javawebinar/basejava/storage/Util.java new file mode 100644 index 0000000..76b7ab2 --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/Util.java @@ -0,0 +1,40 @@ +package ru.javawebinar.basejava.storage; + +import ru.javawebinar.basejava.model.Resume; + +public class Util { + public static final String UUID_1 = "uuid1"; + public static final String UUID_2 = "uuid2"; + public static final String UUID_3 = "uuid3"; + public static final String UUID_4 = "uuid4"; + public static final String UUID_FAKE = "dummy"; + + public static final Resume R1; + public static final Resume R2; + public static final Resume R3; + public static final Resume R4; + public static final Resume FAKE; + + static { +// R1 = new Resume(UUID_1); +// R2 = new Resume(UUID_2); +// R3 = new Resume(UUID_3); +// R4 = new Resume(UUID_3); +// FAKE = new Resume(UUID_FAKE); + + R1 = new Resume(UUID_1, "Name1"); + R2 = new Resume(UUID_2, "Name2"); + R3 = new Resume(UUID_3, "Name3"); + R4 = new Resume(UUID_4, "Name4"); + FAKE = new Resume(UUID_FAKE, "DUMMY"); + + +// R1 = new Resume(UUID_1, 1); +// R2 = new Resume(UUID_2, 2); +// R3 = new Resume(UUID_3, 3); +// R4 = new Resume(UUID_3, 4); +// FAKE = new Resume(UUID_FAKE, 111111); + + } + public static final int STORAGE_LIMIT = 10000; +} diff --git a/test/ru/javawebinar/basejava/storage/junit4/AbstractArrayStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/AbstractArrayStorageTest.java new file mode 100644 index 0000000..494e48b --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/AbstractArrayStorageTest.java @@ -0,0 +1,30 @@ +package ru.javawebinar.basejava.storage.junit4; + + +import org.junit.Assert; +import org.junit.Test; +import ru.javawebinar.basejava.exception.StorageException; +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.Storage; + +import static ru.javawebinar.basejava.storage.Util.STORAGE_LIMIT; + + +public abstract class AbstractArrayStorageTest extends AbstractStorageTest { + protected AbstractArrayStorageTest(Storage storage) { + super(storage); + } + + + @Test(expected = StorageException.class) + public void saveOverFlowException() throws Exception { + try { + for (int i = storage.size() + 1; i <= STORAGE_LIMIT; i++) { + storage.save(new Resume("Name" + i)); + } + } catch (StorageException e) { + Assert.fail(); + } + storage.save(new Resume("Overflow")); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit4/AbstractStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/AbstractStorageTest.java new file mode 100644 index 0000000..9527402 --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/AbstractStorageTest.java @@ -0,0 +1,97 @@ +package ru.javawebinar.basejava.storage.junit4; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import ru.javawebinar.basejava.exception.ExistStorageException; +import ru.javawebinar.basejava.exception.NotExistStorageException; +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.Storage; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; +import static ru.javawebinar.basejava.storage.Util.*; + +public abstract class AbstractStorageTest { + protected Storage storage; + + public AbstractStorageTest(Storage storage) { + this.storage = storage; + } + + @Before + public void setUp() throws Exception { + storage.clear(); + storage.save(R1); + storage.save(R2); + storage.save(R3); + } + + @Test + public void clear() { + storage.clear(); + assertEquals(0, storage.size()); + } + + @Test + public void update() { + Resume r2New = new Resume(UUID_2, "New Name"); + storage.update(r2New); + assertEquals(r2New, storage.get(R2.getUuid())); + } + + @Test(expected = NotExistStorageException.class) + public void updateNonExisting() throws Exception { + storage.update(FAKE); + } + + @Test + public void getAllSorted() throws Exception { + assertEquals(Arrays.asList(R1, R2, R3), storage.getAllSorted()); + assertEquals(3, storage.size()); + } + + @Test + public void save() throws Exception { + storage.save(R4); + assertGet(R4); + assertSize(4); + } + + @Test(expected = ExistStorageException.class) + public void saveExisting() throws Exception { + storage.save(R1); + } + + @Test(expected = NotExistStorageException.class) + public void delete() throws Exception { + storage.delete(R2.getUuid()); + assertSize(2); + storage.get(R2.getUuid()); + } + + @Test(expected = NotExistStorageException.class) + public void deleteNotExisting() throws Exception { + storage.delete(FAKE.getUuid()); // UUID_FAKE + } + + @Test + public void get() throws Exception { + assertGet(R1); + } + + @Test(expected = NotExistStorageException.class) + public void getNonExisting() throws Exception { + storage.get(FAKE.getUuid()); + } + + private void assertSize(int size) { + assertEquals(size, storage.size()); + } + + private void assertGet(Resume resume) { + assertEquals(resume, storage.get(resume.getUuid())); + } + +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit4/ArrayStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/ArrayStorageTest.java new file mode 100644 index 0000000..8f0d0ff --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/ArrayStorageTest.java @@ -0,0 +1,10 @@ +package ru.javawebinar.basejava.storage.junit4; + +import ru.javawebinar.basejava.storage.impl.ArrayStorage; + +public class ArrayStorageTest extends AbstractArrayStorageTest { + + public ArrayStorageTest() { + super(new ArrayStorage()); + } +} diff --git a/test/ru/javawebinar/basejava/storage/junit4/ListStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/ListStorageTest.java new file mode 100644 index 0000000..ae80c4e --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/ListStorageTest.java @@ -0,0 +1,9 @@ +package ru.javawebinar.basejava.storage.junit4; + +import ru.javawebinar.basejava.storage.impl.ListStorage; + +public class ListStorageTest extends ru.javawebinar.basejava.storage.junit4.AbstractStorageTest { + public ListStorageTest() { + super(new ListStorage()); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit4/MapResumeStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/MapResumeStorageTest.java new file mode 100644 index 0000000..c575baa --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/MapResumeStorageTest.java @@ -0,0 +1,10 @@ +package ru.javawebinar.basejava.storage.junit4; + +import ru.javawebinar.basejava.storage.impl.MapResumeStorage; + +public class MapResumeStorageTest extends AbstractStorageTest { + + public MapResumeStorageTest() { + super(new MapResumeStorage()); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit4/MapUuidStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/MapUuidStorageTest.java new file mode 100644 index 0000000..37b87e5 --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/MapUuidStorageTest.java @@ -0,0 +1,10 @@ +package ru.javawebinar.basejava.storage.junit4; + +import ru.javawebinar.basejava.storage.impl.MapUuidStorage; + +public class MapUuidStorageTest extends AbstractStorageTest { + + public MapUuidStorageTest() { + super(new MapUuidStorage()); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit4/SortedArrayStorageTest.java b/test/ru/javawebinar/basejava/storage/junit4/SortedArrayStorageTest.java new file mode 100644 index 0000000..275ea9f --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/SortedArrayStorageTest.java @@ -0,0 +1,10 @@ +package ru.javawebinar.basejava.storage.junit4; + +import ru.javawebinar.basejava.storage.impl.SortedArrayStorage; + +public class SortedArrayStorageTest extends AbstractArrayStorageTest { + + public SortedArrayStorageTest() { + super(new SortedArrayStorage()); + } +} diff --git a/test/ru/javawebinar/basejava/storage/junit4/StorageTestSuite.java b/test/ru/javawebinar/basejava/storage/junit4/StorageTestSuite.java new file mode 100644 index 0000000..5c192bd --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit4/StorageTestSuite.java @@ -0,0 +1,18 @@ +package ru.javawebinar.basejava.storage.junit4; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + + +@RunWith(Suite.class) +@Suite.SuiteClasses( + { + ListStorageTest.class, + MapUuidStorageTest.class, + MapResumeStorageTest.class, + ArrayStorageTest.class, + SortedArrayStorageTest.class + }) +public class StorageTestSuite { + +} diff --git a/test/ru/javawebinar/basejava/storage/junit5/AbstractArrayStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/AbstractArrayStorageTest5.java new file mode 100644 index 0000000..9409122 --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/AbstractArrayStorageTest5.java @@ -0,0 +1,56 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import ru.javawebinar.basejava.exception.StorageException; +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.Storage; + +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.*; +import static ru.javawebinar.basejava.storage.Util.STORAGE_LIMIT; + + +public abstract class AbstractArrayStorageTest5 extends AbstractStorageTest5 { + + protected AbstractArrayStorageTest5(Storage storage) { + super(storage); + } + + + @Nested + class SaveOverflow { + + @BeforeEach + void setUp() { + storage.clear(); + } + + @Test + @DisplayName("Should not throw within size limit, then throws when overflow") + void fill() { + // arrange + String uuid = "New item"; + Executable throwingExecutable = () -> { + storage.save(new Resume(uuid, "Extra soldier")); + }; + + // act and assert + assertDoesNotThrow(() -> IntStream.iterate(0, n -> n + 1). + limit(STORAGE_LIMIT). + mapToObj(i -> new Resume("Name" + i, "Name" + i)). + forEach(storage::save)); + + RuntimeException thrown = assertThrows( + StorageException.class, throwingExecutable, "Should throw generic StorageException" + ); + + assertEquals("Storage overflow", thrown.getMessage()); + } + } + +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit5/AbstractStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/AbstractStorageTest5.java new file mode 100644 index 0000000..f942f2c --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/AbstractStorageTest5.java @@ -0,0 +1,130 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.javawebinar.basejava.exception.ExistStorageException; +import ru.javawebinar.basejava.exception.NotExistStorageException; +import ru.javawebinar.basejava.model.Resume; +import ru.javawebinar.basejava.storage.Storage; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.*; +import static ru.javawebinar.basejava.storage.Util.*; + +public abstract class AbstractStorageTest5 { + protected Storage storage; + + protected AbstractStorageTest5(Storage storage) { + this.storage = storage; + } + + @BeforeEach + void beforeEach() { + storage.clear(); + storage.save(R1); + storage.save(R2); + storage.save(R3); + } + + @Test + void size() throws Exception { + assertSize(3); + } + + @Test + void clear() throws Exception { + storage.clear(); + assertSize(0); + } + + + @Test + void update() throws Exception { + Resume r2New = new Resume(UUID_2, "New Name"); + storage.update(r2New); + + assertEquals(r2New, storage.get(R2.getUuid())); +// assertSame(r2New, storage.get(UUID_2)); + } + + + @Test + void updateNonExisting() { + assertThrows( + NotExistStorageException.class, + () -> storage.update(FAKE) + ); + } + + @Test + void save() throws Exception { + storage.save(R4); + + assertSize(4); + assertSame(R4, storage.get(UUID_4)); + } + + + @Test + void saveExisting() throws Exception { + assertThrows(ExistStorageException.class, + () -> storage.save(R1)); + } + + + @Test + void delete() throws Exception { + storage.delete(UUID_2); + assertAll("storage size is decreased, and access to deleted item correctly throws", + () -> assertEquals(2, storage.size()), + () -> assertThrows(NotExistStorageException.class, + () -> storage.get(UUID_2)) + ); + } + + @Test + void deleteNonExisting() { + assertThrows( + NotExistStorageException.class, + () -> storage.delete(FAKE.getUuid()) + ); + } + + + @Test + void getAllSorted() throws Exception { + assertEquals(Arrays.asList(R1, R2, R3), storage.getAllSorted()); + assertSize(3); + } + +// @Test +// void getAll() throws Exception { +// Resume[] test = new Resume[]{R1, R2, R3}; +// assertEquals(3, storage.getAll().length); +// assertArrayEquals(test, storage.getAll()); +// } + + + @Test + void get() throws Exception { + assertGet(R1); + } + + @Test + void getNonExistinging() { + assertThrows( + NotExistStorageException.class, + () -> storage.get(FAKE.getUuid()) + ); + } + + + protected void assertSize(int size) { + assertEquals(size, storage.size()); + } + + private void assertGet(Resume resume) { + assertEquals(resume, storage.get(resume.getUuid())); + } +} diff --git a/test/ru/javawebinar/basejava/storage/junit5/ArrayStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/ArrayStorageTest5.java new file mode 100644 index 0000000..05e765d --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/ArrayStorageTest5.java @@ -0,0 +1,12 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.DisplayName; +import ru.javawebinar.basejava.storage.impl.ArrayStorage; + +@DisplayName("ArrayStorage implementation") +public class ArrayStorageTest5 extends AbstractArrayStorageTest5 { + + public ArrayStorageTest5() { + super(new ArrayStorage()); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit5/ListStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/ListStorageTest5.java new file mode 100644 index 0000000..83fe040 --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/ListStorageTest5.java @@ -0,0 +1,11 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.DisplayName; +import ru.javawebinar.basejava.storage.impl.ListStorage; + +@DisplayName("ListStorage implementation") +class ListStorageTest5 extends AbstractStorageTest5 { + public ListStorageTest5() { + super(new ListStorage()); + } +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/junit5/MapResumeStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/MapResumeStorageTest5.java new file mode 100644 index 0000000..84e1136 --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/MapResumeStorageTest5.java @@ -0,0 +1,11 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.DisplayName; +import ru.javawebinar.basejava.storage.impl.MapResumeStorage; + +@DisplayName("MapResumeStorage implementation") +public class MapResumeStorageTest5 extends AbstractStorageTest5 { + public MapResumeStorageTest5() { + super(new MapResumeStorage()); + } +} diff --git a/test/ru/javawebinar/basejava/storage/junit5/MapUuidStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/MapUuidStorageTest5.java new file mode 100644 index 0000000..75ddebb --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/MapUuidStorageTest5.java @@ -0,0 +1,11 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.DisplayName; +import ru.javawebinar.basejava.storage.impl.MapUuidStorage; + +@DisplayName("MapUuidStorage implementation") +public class MapUuidStorageTest5 extends AbstractStorageTest5 { + public MapUuidStorageTest5() { + super(new MapUuidStorage()); + } +} diff --git a/test/ru/javawebinar/basejava/storage/junit5/SortedArrayStorageTest5.java b/test/ru/javawebinar/basejava/storage/junit5/SortedArrayStorageTest5.java new file mode 100644 index 0000000..463affd --- /dev/null +++ b/test/ru/javawebinar/basejava/storage/junit5/SortedArrayStorageTest5.java @@ -0,0 +1,12 @@ +package ru.javawebinar.basejava.storage.junit5; + +import org.junit.jupiter.api.DisplayName; +import ru.javawebinar.basejava.storage.impl.SortedArrayStorage; + +@DisplayName("SortedArrayStorage implementation") +public class SortedArrayStorageTest5 extends AbstractArrayStorageTest5 { + + public SortedArrayStorageTest5() { + super(new SortedArrayStorage()); + } +} \ No newline at end of file