diff --git a/.gitignore b/.gitignore index 50d27906..caa066b7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ out log lib -storage \ No newline at end of file + diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 00000000..59499bce --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/README.md b/README.md index 3047ee38..e288257e 100644 --- a/README.md +++ b/README.md @@ -1,200 +1,120 @@ # Курс BaseJava (обновленный и переработанный) -## Разработка web-приложения "База данных резюме" - -В данном курсе вы создадите с нуля web-приложение, реализуя разные способы хранения резюме. Проект включает в себя следующее: - - **Технологии:** Java 8, GitHub/Git, JUnit, Logging, GSON, JAXB, SQL, PostgreSQL, Сервлеты, HTML, JSP, JSTL, Tomcat, Maven и многое другое - - **Различные способы реализации хранения резюме:** - - в сортированном и не сортированном массиве - - в коллекциях (List, Map) - - в файловой системе: - - с использованием File и Path API +## Разработка Web приложения "База данных резюме" + - используем: Java 8, IntelliJ IDEA, + GitHib/Git, Сервлеты, JSP, JSTL, Tomcat, JUnit, PostgreSQL, GSON, JAXB + - хранение резюме + - в памяти на основе массива, отсортированного массива, списка и ассоциированного массива (Map) + - в файловой системе (File API и Java 7 NIO File API) - в стандартной и кастомной сериализации Java - - в формате JSON ([Google Gson](https://en.wikipedia.org/wiki/Gson)) - - в формате XML ([JAXB](https://ru.wikipedia.org/wiki/Java_Architecture_for_XML_Binding)) - - в реляционной базе [PostgreSQL](https://ru.wikipedia.org/wiki/PostgreSQL) - - **Установку (деплой) web-приложения:** - - в контейнер сервлетов [Tomcat](https://ru.wikipedia.org/wiki/Apache_Tomcat) - - на [собственный выделенный сервер](https://github.com/JavaOps/startup) - -> Любое знание стоит воспринимать как подобие семантического дерева: убедитесь в том, что понимаете фундаментальные принципы, то есть ствол и крупные ветки, прежде чем лезть в мелкие листья-детали. Иначе последним не на чем будет держаться - -— Илон Маск - -## Программа курса - -#### [Занятие 1](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson01.md) - - Обзор курса и методики обучения - - Подготовка и настройка рабочего окружения - - Подходы, применяемые при разработке ПО - - Обзор инструментов и технологий, используемых Java-разработчиками - - Введение в язык Java: история создания, JDK, JVM, JRE, JIT-компиляция - - Системы управления версиями. Git - - Домашнее задание - -#### [Занятие 2](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson02.md) - - Типы данных - - Введение в объектно-ориентированное программирование - - Принципы ООП - - Классы и объекты - - Классы-обертки - - Модификаторы доступа - - Конструктор - - Структура памяти java-программы: Heap (куча), Stack (стек) - - Пакеты - - Домашнее задание - -#### [Занятие 3](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson03.md) - - Разбор домашнего задания - - Обзор суперкласса Object - - Связь между equals() и hashCode() - - Статические методы и переменные - - Программирование с помощью интерфейсов - - Абстрактные классы - - Сложность алгоритмов - - Паттерн проектирования Template Method - - Домашнее задание + - в формате JSON (Google Gson) + - в формате XML (JAXB) + - в реляционной базе PostgreSQL + - деплой веб приложения + - в контейнер сервлетов Tomcat + - в облачный сервис Heroku + +Приложение будет разрабатываться начиная со первого занятия, основываясь на базовых темах курса: +**объектная модель, коллекции, система ввода-вывода, работа с файлами, сериализация, работа с XML, JSON, SQL, персистентность в базу данных (PostgreSQL), сервлеты, HTML/JSP/JSTL, веб-контейнер Tomcat, модульные тесты JUnit, java.util.Logging, система контроля версий Git.** + +> Любое знание стоит воспринимать как подобие семантического дерева: убедитесь в том, что понимаете фундаментальные принципы, то есть ствол и крупные ветки, прежде чем лезть в мелкие листья-детали. Иначе последним не на чем будет держаться. + +[*— Илон Маск](https://ru.wikipedia.org/wiki/Маск,_Илон) + +# Изучайте [первое открытое занятие](lesson/lesson1.md). +### Внизу урока есть первое домашнее задание, по которому можно оценить свой уровень готовности к проекту. + +## Программа +### [Регистрация](http://javaops.ru/reg/basejava) +### Открытое занятие 1 + - [Презентация проекта](lesson/lesson1.md#-Вебинар-ПРЕЗЕНТАЦИЯ-обучения) + - [Разработка ПО](lesson/lesson1.md#-1-Разработка-ПО) + - [Обзор языка Java](lesson/lesson1.md#-3-Обзор-языка-java) + - [Системы управления версиями. Git](lesson/lesson1.md#-4-Системы-управления-версиями-git) + - [ПЕРВОЕ ДОМАШНЕЕ ЗАДАНИЕ](lesson/lesson1.md#Домашнее-задание-hw1) + +### Занятие 2 + - [Принципы ООП](lesson/lesson2.md#Принципы-ООП) + - [Структура памяти: куча, стек, регистры, константы](lesson/lesson2.md#Структура-памяти-куча-стек-регистры-константы) + - [Типы данных. Пакеты](lesson/lesson2.md#Типы-данных-Пакеты) + +### Занятие 3 + - [Объектная модель в Java](lesson/lesson3.md#Объектная-модель-в-java) + - [Сложность алгоритмов](lesson/lesson3.md#Сложность-алгоритмов) + - [Паттерн проектирования Шаблонный метод](https://github.com/JavaOPs/JavaSE-Web/blob/master/lesson/lesson3.md#Паттерн-проектирования-Шаблонный-метод) -#### [Занятие 4](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson04.md) - - Разбор домашнего задания - - Конструктор - - Работа со строками: String, StringBuilder, StringBuffer - - String literal pool - - Исключения (Exceptions) - - Ключевые слова: this, super - - Reflection - - Аннотации - - Введение в модульное тестирование. JUnit - - Домашнее задание - -#### [Занятие 5](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson05.md) - - Разбор домашнего задания - - Коллекций. Иерархия классов - - Списки (List) - - Множества (Set) - - Ассоциативные массивы (Map) - - Введение в Iterator - - Домашнее задание +### Занятие 4 + - [Работа со строками](lesson/lesson4.md#Работа-со-строками) + - [Исключения](lesson/lesson4.md#Исключения) + - [Reflection. Аннотации. Модульное тестирование](lesson/lesson4.md#reflection-Аннотации-Модульное-тестирование) + +### Занятие 5 + - [Контейнеры/коллекции](lesson/lesson5.md#Контейнерыколлекции) -#### [Занятие 6](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson06.md) - - Разбор домашнего задания - - Паттерн проектирования Iterator - - Autoboxing и Unboxing - - Вложенные классы - - Внутренние классы - - Локальные классы - - Анонимные классы - - Введение в лямбда-выражения - - Функциональный интерфейс - - Домашнее задание - -#### [Занятие 7](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson07.md) - - Разбор домашнего задания - - Дженерики (Generic) - - Введение в логирование. Log4J, Java Logging API - - Паттерн проектирования Singleton - - Перечисления (Enum) - - Объектная модель - - Домашнее задание - -#### [Занятие 8](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson08.md) - - Разбор домашнего задания - - Классы работы с датами: Date, Calendar, TimeZone - - Дата и время в Java 8+ - - File API - - Освобождение ресурсов: try-with-resources - - Домашнее задание - -#### [Занятие 9](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson09.md) - - Разбор домашнего задания - - Обзор пакета java.io - - Классы чтения/записи потоков: InputStream и OutputStream - - Паттерн проектирования Decorator - - Классы чтения/записи символов: Reader и Writer - - Сериализация объектов - - Обзор пакета java.nio - - Введение в Java 8+ Stream API - - Домашнее задание - -#### [Занятие 10](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson10.md) - - Разбор домашнего задания - - Паттерн проектирования Strategy - - Работа с XML (JAXB) - - Работа с JSON (GSON) - - Классы чтения/записи примитивных типов: DataInputStream и DataOutputStream - - Домашнее задание - -#### [Занятие 11](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson11.md) - - Многопоточность - - Закон Мура и Амдала - - Потоки. Синхронизация доступа - - Обзор методов класса Object - - Ленивая инициализация - - Java Memory Model - - Deadlock - - Домашнее задание +### Занятие 6 + - [Iterator / Iterable. Вложенные, внутренние, локальные и анонимные классы](lesson/lesson6.md#iterator--iterable-Вложенные-внутренние-локальные-и-анонимные-классы) + - [Новое в Java 8](lesson/lesson6.md#Новое-в-java-8) + +### Занятие 7 + - [Параметризация. Стирание типов](lesson/lesson7.md#Параметризация-Стирание-типов) + - [Логирование](lesson/lesson7.md#Логирование) + - [Синглетон, Enum](lesson/lesson7.md#Синглетон-enum) + +### Занятие 8 + - [Работа с датами и временем](lesson/lesson8.md#Работа-с-датами-и-временем) + - [Работа с файлами и ресурсами](lesson/lesson8.md#Работа-с-файлами-и-ресурсами) + +### Занятие 9 + - [Ввод/вывод](lesson/lesson9.md#Вводвывод) + - [Сериализация](lesson/lesson9.md#Сериализация) + - [NIO](lesson/lesson9.md#nio) + - [Основы Java 8 Stream API](lesson/lesson9.md#Основы-java-8-stream-api) + +### Занятие 10 + - [Формат XML. Работа с XML в Java](lesson/lesson10.md#Формат-xml-Работа-с-xml-в-java) + - [JSON](lesson/lesson10.md#json) + - [DataInputStream / DataOutputStream](lesson/lesson10.md#datainputstream--dataoutputstream) + +### Занятие 11 + - [Многопоточность. Параллельное выполнение.](lesson/lesson11.md#Многопоточность-Параллельное-выполнение) + - [Потоки. Синхронизация](lesson/lesson11.md#Потоки-Синхронизация) + - [Ленивая инициализация, JMM](lesson/lesson11.md#Ленивая-инициализация-jmm) -#### [Занятие 12](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson12.md) - - Разбор домашнего задания - - Обзор классов java.util.concurrent - - Синхронизаторы - - ThreadLocal-переменные - - Сравнение с обменом (Compare-and-swap) - - Домашнее задание - -#### [Занятие 13](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson13.md) - - Разбор домашнего задания - - Введение в реляционные базы данных - - Язык SQL - - Обзор NoSQL баз данных - - Установка и настройка СУБД PostgreSQL - - Работа с базами данных из IDEA - - Конфигурирование базы данных и каталога хранения - - Подключение базы данных к проекту - - Обзор JDBC-архитектуры - - Домашнее задание - -#### [Занятие 14](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson14.md) - - Разбор домашнего задания - - Операции соединения таблиц. JOIN - - Транзакции - - Требования к транзакциям. ACID - - Уровни изоляции транзакций в SQL - - Установка и настройка контейнера сервлетов Tomcat - - Домашнее задание - -#### [Занятие 15](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson15.md) - - Разбор домашнего задания - - Введение в HTML - - Основы протокола HTTP - - Настройка web.xml - - Деплой web-приложения в Tomcat - - Сервлеты - - Домашнее задание +### Занятие 12 + - [java.util.concurrent](lesson/lesson12.md#javautilconcurrent) + +### Занятие 13 + - [Базы данных. Реляционные СУБД. PostgreSQL](lesson/lesson13.md#Базы-данных-Реляционные-СУБД-postgresql) + - [Конфигурирование данных в Java проекте](lesson/lesson13.md#Конфигурирование-данных-в-java-проекте) + - [Подключение DB в проект](lesson/lesson13.md#Подключение-db-в-проект) + +### Занятие 14 + - [JOIN](lesson/lesson14.md#join) + - [Транзакции](lesson/lesson14.md#Транзакции) + - [Установка/запуск Tomcat](lesson/lesson14.md#Установказапуск-tomcat) + +### Занятие 15 + - [HTML, Tomcat](lesson/lesson15.md#html-tomcat) + - [Сервлеты](lesson/lesson15.md#Сервлеты) -#### [Занятие 16](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson16.md) - - Разбор домашнего задания - - Жизненный цикл сервлета - - Создание динамических страниц. JSP - - Расширенные возможности JSP. JSTL - - Redirect и Forward - - CRUD-операции - - Домашнее задание +### Занятие 16 + - [JSP](lesson/lesson16.md#jsp) + - [JSTL](lesson/lesson16.md#jstl) -#### [Занятие 17](https://github.com/JavaWebinar/basejava/blob/lesson/lesson/lesson17.md) - - Разбор домашнего задания - - Деплой приложения на [собственный выделенный сервер](https://github.com/JavaOps/startup) - - Загрузка классов в Java. Classloader - - Домашнее задание +### Занятие 17 + - [Деплой в Heroku](lesson/lesson17.md#Деплой-в-heroku) + - [Classloader](lesson/lesson17.md#classloader) + - [Обзор Java Enterprise](lesson/lesson17.md#Обзор-java-enterprise) ## Рекомендуемые книги -- [Яков Файн, "Программирование на Java для начинающих"](http://myflex.org/books/java4kids/java4kids.htm) -- [Книги по Java: от новичка до профессионала](https://proglib.io/p/java-books-2019/) -- [Джошуа Блох, "Java. Эффективное программирование, 3-е издание"](https://www.ozon.ru/context/detail/id/148627191/) -- [Роберт Мартин, "Чистый код"](https://www.ozon.ru/context/detail/id/142429922/) -- [Серия Head First, "Паттерны проектирования"](https://www.ozon.ru/context/detail/id/144233005/) -- [Вайсфельд Мэтт, "Объектно-ориентированный подход"](https://www.ozon.ru/context/detail/id/166375103/?stat=YW5fMQ%3D%3D) - -## Ресурсы в сети -- [EduTools плагин от JetBrains для изучения Kotlin, Java, Python, Scala и других языков](http://javaops.ru/view/story/story21#edutools) -- [JetBrains Academy — интерактивный учебный курс по Java](https://www.jetbrains.com/ru-ru/academy/) +- YAKOV FAIN: Программирование на Java для начинающих +- Книги по Java: от новичка до профессионала +- Джошуа Блох: Java. Эффективное программирование, 2-е издание +- Гамма, Хелм, Джонсон: Приемы объектно-ориентированного проектирования. Паттерны проектирования +- Редмонд Э.: Семь баз данных за семь недель. Введение в современные базы данных и идеологию NoSQL. + +## Ресуры в сети +- [Руководство по Java Core](http://proselyte.net/tutorials/java-core/) +- [Java. Базовый курс](https://stepik.org/course/Java-Базовый-курс-187) +- intuit: Программирование на Java +- Основы программирования на Java: учебное пособие diff --git a/config/populate.sql b/config/populate.sql index 696e843b..50aa1f9c 100644 --- a/config/populate.sql +++ b/config/populate.sql @@ -1,3 +1,5 @@ +DELETE FROM resume; + INSERT INTO resume (uuid, full_name) VALUES ('7de882da-02f2-4d16-8daa-60660aaf4071', 'Name1'), ('a97b3ac3-3817-4c3f-8a5f-178497311f1d', 'Name2'), diff --git a/config/resumes.properties b/config/resumes.properties index ff9f0f81..9986b766 100644 --- a/config/resumes.properties +++ b/config/resumes.properties @@ -1,6 +1,7 @@ -storage.dir=C:/projects/basejava/storage - -# Replace by Heroku credentials -db.url=jdbc:postgresql://localhost:5432/resumes -db.user=postgres -db.password=postgres \ No newline at end of file +storage.dir=/home/op/java/basejava/storage +#db.url=jdbc:postgresql://localhost:5432/resumes +#db.user=postgres +#db.password=postgres +db.url=jdbc:postgresql://ec2-79-125-12-27.eu-west-1.compute.amazonaws.com:5432/dcthekgt0bu69 +db.user=hebdymejavtknm +db.password=8daa7a7d8c56ed03f2f8a52de9745398ebb53b4b50cf764c6b233d286d71e09e \ No newline at end of file diff --git a/lesson/lesson1.md b/lesson/lesson1.md new file mode 100644 index 00000000..1b1d00c9 --- /dev/null +++ b/lesson/lesson1.md @@ -0,0 +1,98 @@ +## ![video](https://cloud.githubusercontent.com/assets/13649199/13672715/06dbc6ce-e6e7-11e5-81a9-04fbddb9e488.png) [Вебинар ПРЕЗЕНТАЦИЯ обучения](https://drive.google.com/file/d/0B_4NpoQW1xfpNzdqT2hOcUJ6TGs) +- [Так будет выглядеть мое резюме в разабатываемом на этом проекте приложении](https://javawebinar.github.io/) + +## Для участия необходимо: +- Установить JDK8 (выбрать Accept License Agreement) +- Установить систему управления версиями Git (опции по умолчанию) +- Создать аккаунт на GitHub +- Установить IntelliJ IDEA +> Выбирать Ultimate, 30 days trial (нам понадобится SQL, Tomcat, JSP). Ключ на 6 месяцев выдается на первом занятии. + +# Первое открытое занятие +## ![video](https://cloud.githubusercontent.com/assets/13649199/13672715/06dbc6ce-e6e7-11e5-81a9-04fbddb9e488.png) 1. [Разработка ПО](https://drive.google.com/open?id=0B_4NpoQW1xfpVjZUTEpvVUN1TTA) +- [Книга: Мифический человеко-месяц](https://ru.wikipedia.org/wiki/Мифический_человеко-месяц) +- [Размеры проектов в количестве строк кода](https://medium.freecodecamp.com/the-biggest-codebases-in-history-a128bb3eea73) +- [Соглашения по именованию](http://www.intuit.ru/studies/courses/16/16/lecture/27113?page=4) +- [Методологии разработки ПО](https://dou.ua/forums/topic/14015/) + - **Доступ из России через прокси (например [friGate CDN](https://chrome.google.com/webstore/detail/frigate-cdn-smooth-access/mbacbcfdfaapbcnlnbmciiaakomhkbkb))** +- [Ещё раз про семь основных методологий разработки](https://habrahabr.ru/company/edison/blog/269789/) + +## ![video](https://cloud.githubusercontent.com/assets/13649199/13672715/06dbc6ce-e6e7-11e5-81a9-04fbddb9e488.png) 2. [Обзор инструментов и технологий](https://drive.google.com/file/d/0B_4NpoQW1xfpTXJYU2xZbjN2d2M) +- [Bash — шпаргалка для начинающих](https://tproger.ru/translations/bash-cheatsheet) +- [Типичный тест SQL на собеседованиях](https://habrahabr.ru/post/181033/) +- **Обновление!!** [Java Tools and Technologies Landscape Report 2016](https://zeroturnaround.com/rebellabs/java-tools-and-technologies-landscape-2016/) + - [Java Tools and Technologies Landscape for 2014](http://zeroturnaround.com/rebellabs/java-tools-and-technologies-landscape-for-2014) +- Дополнительно: + - [Автоматизированные сборки в Java](http://www.quizful.net/post/automated-builds-java) + +## ![video](https://cloud.githubusercontent.com/assets/13649199/13672715/06dbc6ce-e6e7-11e5-81a9-04fbddb9e488.png) 3. [Обзор языка Java](https://drive.google.com/open?id=0B_4NpoQW1xfpTU5SSElhUjlGNnc) +- [Java](http://ru.wikipedia.org/wiki/Java), [JVM](http://ru.wikipedia.org/wiki/Виртуальная_машина_Java), [JIT-компиляция](http://ru.wikipedia.org/wiki/JIT) +- [Что такое Java? История создания](http://www.intuit.ru/studies/courses/16/16/lecture/27105) +- [Programming languages TIOBE Index](http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html) + +![jvm](https://cloud.githubusercontent.com/assets/18701152/15219296/e6c67e86-186b-11e6-986f-651a87deec6c.png) + +- [Java Microbenchmark JMH](https://github.com/JavaOPs/masterjava#Занятие-2) используем на курсе Masterjava +- [Oracle Java8 Home](http://docs.oracle.com/javase/8/docs/index.html) +- [ME](http://ru.wikipedia.org/wiki/Java_Platform,_Micro_Edition), [SE](http://en.wikipedia.org/wiki/Java_Platform,_Standard_Edition) (русский), [EE](http://en.wikipedia.org/wiki/Java_Platform,_Enterprise_Edition) ([русский](http://ru.wikipedia.org/wiki/Java_Platform,_Enterprise_Edition)) +- Дополнительно: + - [Java version and vendor data analyzed](https://plumbr.eu/blog/java/java-version-and-vendor-data-analyzed-2016-edition) + - [Most Popular Java EE Servers](https://dzone.com/articles/most-popular-java-ee-servers-2016-edition) + - [Понимаем основы Java garbage collection](https://ggenikus.github.io/blog/2014/05/04/gc) + +## ![video](https://cloud.githubusercontent.com/assets/13649199/13672715/06dbc6ce-e6e7-11e5-81a9-04fbddb9e488.png) 4. [Системы управления версиями. Git](https://drive.google.com/file/d/0B9Ye2auQ_NsFSUNrdVc0bDZuX2s) +### Настройка проекта +- Создать на GitHub репозиторий `basejava` +- git занести в переменная окружения PATH, перезапустить cmd +- Создайте локальную копию проекта: `git clone https://github.com/JavaOps/basejava.git` +- Перейти в каталог проекта: `cd basejava` +- Настроить git в локальном проекте на свой проект в GitHub: + - `git remote -v` + - `git remote set-url origin https://github.com/[твой_GITHUB_аккаунт]/[твой_репозиторий].git` - настройка pull + - `git remote set-url --push origin https://github.com/[твой_GITHUB_аккаунт]/[твой_репозиторий].git` - настройка push + - `git push -u origin master` + +### Система управления версиями. VCS/DVSC + +![image](https://cloud.githubusercontent.com/assets/18701152/15219746/9295a2fe-186d-11e6-876b-c61cc9be71e4.png) + +- Ресурсы: + - Интерактивная Git обучалка + - Еще одна интерактивная обучалка, по русски + - Книга Git + - Working with remote repositories + - Видео по обучению Git + - Git Overview + - Видеокурс по Git + - [Основы Git за 20 минут](https://www.youtube.com/watch?v=TMeZGvtQnT8) +- [Популярность разный VSC](http://www.netinstructions.com/the-case-for-git/) +- Книга по Git + +## Домашнее задание HW1 +- Создайте в IntelliJ IDEA новый проект, выбрав каталог `basejava`, в котором находится ваш репозиторий: + +![newproject](https://user-images.githubusercontent.com/13649199/27245917-c66f0b5a-52f6-11e7-98dc-f88d0198b5c4.png) + +![next](https://user-images.githubusercontent.com/13649199/27245921-c88b4570-52f6-11e7-83a3-e52627468be7.png) + +![finish](https://user-images.githubusercontent.com/13649199/27245924-cab3618e-52f6-11e7-9655-4293149b4126.png) + +- Реализуйте класс `ArrayStorage`: хранение резюме на основе массива (методы `clear, get, save, delete, getAll, size`). Не используйте в решении коллекции, реализацию на их основе мы добавим позднее. +- Протестируйте вашу реализацию, запустив `MainTestArrayStorage.main()`: в IDEA слева на полях зеленая стрелка. +- Протестируйте вашу реализацию интерактивно с помощью `MainArray.main()`. +- Дополнительные материалы по IntelliJ IDEA + - Idea Wiki (поставить кодировку UTF-8, поменять фонт по умолчанию на DejaVu) + - Отладчик IntelliJ IDEA + - Эффективная работа с кодом в IntelliJ IDEA + +### Optional +- Модифицировать класс `ArrayStorage`: хранить все резюме в начале storage (без дырок null), чтобы не перебирать каждый раз все 10000 элементов. +``` +Хранеие резюме в storage (от 0 до size-1 элементов null нет): + +r1, r2, r3,..., rn, null, null,..., null +<---- size -----> +<---- storage.length (10000)----------> +``` +- Посмотреть на класс `Arrays`. Там есть полезные вещи, которые могут упростить код `ArrayStorage`. +- Протестируйте реализацию, запустив MainArray.main(): в IDEA слева на полях зеленая стрелка. diff --git a/lesson/lesson10.md b/lesson/lesson10.md new file mode 100644 index 00000000..1c279e7a --- /dev/null +++ b/lesson/lesson10.md @@ -0,0 +1,19 @@ + +# Десятое занятие + +## Разбор Домашнего Задания-9: + +## Формат XML. Работа с XML в Java +- XML формат и технологии +- Wiki: XML, XSL , DOM, SAX, StAX, JAXB +- Работа с XML в Java. Реализация хранения в XML. + +## JSON +- JSON. JSON в JavaScript. REST +- Работа с JSON в Java: Google GSON и Jackson. Реализация хранения в JSON. + +## DataInputStream / DataOutputStream +- Реализация Store на основе `DataInputStream/DataOutputStream`. + +## Домашнее задание +- Сделать и протестировать реализацию `DataStreamSerializer` \ No newline at end of file diff --git a/lesson/lesson11.md b/lesson/lesson11.md new file mode 100644 index 00000000..1a1e7a91 --- /dev/null +++ b/lesson/lesson11.md @@ -0,0 +1,31 @@ + +# Одиннадцатое занятие + +## Многопоточность. Параллельное выполнение. +![Закон Мура](https://www.karlrupp.net/wp-content/uploads/2015/06/40-years-processor-trend.png) +- Закон Мура +- Закон Амдала + +![Concurrent vs Parallel](https://joearms.github.io/images/con_and_par.jpg) + +## Потоки. Синхронизация +- Потоки выполнения. Синхронизация. +- Методы wait(), notify(), notifyAll() класса Object + +## Ленивая инициализация, JMM +- Параллелизм в Java +- Реализация Singleton в JAVA +- Double checked locking +- Java Memory Model. final, volatile +- Initialization-on-demand holder idiom + +### Ресурсы +- Алексей Владыкин, Основы многопоточность в Java +- Виталий Чибриков, Java. Многопоточность +- Computer Science Center, курс Параллельное программирование +- Юрий Ткач, курс Advanced Java - Concurrency +- Головач, курс Java Multithreading + +## Домашнее задание +- Реализовать deadlock +- Взаимная блокировка diff --git a/lesson/lesson12.md b/lesson/lesson12.md new file mode 100644 index 00000000..47156cdd --- /dev/null +++ b/lesson/lesson12.md @@ -0,0 +1,35 @@ + +# Двенадцатое занятие + +## Разбор Домашнего Задания-11: реализация dead lock. + +## java.util.concurrent +- Обзор java.util.concurrent.* +- Compare-and-swap +- Справочник по синхронизаторам java.util.concurrent.* +- Использование ThreadLocal переменных + +> Замечания по видео: + + ThreadLocal DATE_FORMAT = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); + }; + }; + +можно написать через лямбду: + + ThreadLocal.withInitial(() -> new SimpleDateFormat("dd.MM.yyyy HH:mm:ss")); + +А лучше использовать потокобезопасный `DateTimeFormatter` Java 8 Time API: + + DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); + +## Разбор домашнего задания 10го урока + +## Домашнее задание: +- Установить PostgreSQL +- Посомтреть на реляционные базы данных и SQL: + - Введение в базы данных + - Основы SQL diff --git a/lesson/lesson13.md b/lesson/lesson13.md new file mode 100644 index 00000000..2ad74ff1 --- /dev/null +++ b/lesson/lesson13.md @@ -0,0 +1,29 @@ + +# Тринадцатое занятие + +### Базы данных. Реляционные СУБД. PostgreSQL +- DB-Engines Ranking +- Реляционная СУБД +- Введение в базы данных +- Реляционные базы vs NoSQL. SQL. Денормализация. PK, FK, Cascade +- PostgreSQL. Надёжность +- Создание базы резюме. Работа с базами данных из IDEA +- IDEA Database tools. + +### Конфигурирование данных в Java проекте +- Properties sample +- Конфигурирование DB и каталога хранения + +### Подключение DB в проект +- JDBC. JDBC Architecture. +- ConnectionFactory. Реализация SqlStorage. +- Ресурсы: + - Книга: Семь баз данных за семь недель. Введение в современные базы данных и идеологию NoSQL + - Работа с базами данных с помощью JDBC драйвера + - Уроки по JDBC + +### ![hw](https://cloud.githubusercontent.com/assets/13649199/13672719/09593080-e6e7-11e5-81d1-5cb629c438ca.png) Домашнее задание HW13 +- Доделать `SqlStorage` без контактов и секций. + - Для работы с DB надо в lib и проект добавить драйвер базы данных + - Запустить `SqlStorageTest` (в `AbstractStorageTest` контакты и секции закоменченны), креденшелы к базе взять из `Config` +- Вынести общий код (`getConnection(), prepareStatement, catch SQLException`) в класс `SqlHelper`. diff --git a/lesson/lesson14.md b/lesson/lesson14.md new file mode 100644 index 00000000..f625d1d0 --- /dev/null +++ b/lesson/lesson14.md @@ -0,0 +1,26 @@ + +# Четырнадцатое занятие + +### Разбор HW13 + +### JOIN +- LEFT, RIGHT, INNER JOIN +- Добавляем в `SqlStorage` контакты + +### Транзакции. +- Транзакция. ACID. Уровни изоляции транзакций. +- Уровни изоляции транзакций в SQL +- Добавляем в `SqlStorage` транзакции +- Batch execute. + +### Установка/запуск Tomcat +- Скачать и установить Tomcat 8. Устанавливать лучше простым копированием из архива в каталог (в том числе и для unix). Следите чтобы в пути не было пробелов и национальных букв. +- Для доступа к Tomсat Manager добавьте в конфигурацию Tomcat `TOMCAT_HOME\conf\tomcat-users.xml` права: +``` + +``` +- Запуск из `TOMCAT_HOME\bin\`: `catalina.bat start` + +## Домашнее задание HW14 +- Закончить реализацию `SqlStorage` с контактами +- Добавить `TextSection` в базу данных (`init_db.sql`) и `SqlStorage`. diff --git a/lesson/lesson15.md b/lesson/lesson15.md new file mode 100644 index 00000000..4939684e --- /dev/null +++ b/lesson/lesson15.md @@ -0,0 +1,26 @@ +# Пятнадцатое занятие + +### Разбор HW14 + +### HTML, Tomcat +- Протокол HTTP. Смотрим демо приложение в Chrome -> Инструменты разработчика +- Добавление в проект Web Facet. web.xml. Постороение/cтруктура WAR. Статические ресурсы. +- Настройка и деплой в Tomcat. Tomcat manager. +- Запуск Tomcat из IDEA. Динамическое обновление без передеплоя. + +### Сервлеты +- Создаем Servlet. Параметры. Кодировка. +- Дополнительно: + - How do servlets work? + - Язык программирования Java и среда NetBeans: Введение в сетевое программирование + - Основы работы с HTML + - Учебник HTML + - Технологии Java для разработки веб-приложений + - Таблицы стилей CSS + - Основы JavaScript + +## Домашнее задание HW15 +- Сделать реализацию `SqlStorage.getAll` через 2 отдельных запроса: отдельно резюме и отдельно контакты. +- Добавить в реализацию `SqlStorage` и в базу секции (кроме `OrganizationSection`). Для `ListSection` склеиваем строки через `\n`. +- Сделать отображение таблицы резюме в сервлете. + - HTML таблицы diff --git a/lesson/lesson16.md b/lesson/lesson16.md new file mode 100644 index 00000000..6e431f31 --- /dev/null +++ b/lesson/lesson16.md @@ -0,0 +1,21 @@ +# Шестнадцатое занятие + +### Разбор HW15 +- Почему вы никогда не должны использовать MongoDB +- Жизненный цикл сервлета +- Tomcat maxThreads configuration + +### JSP +- Что такое JSP. Wiki JSP +- Predefined Variables in JSP +- Стандартные элементы action +- How to use relative paths in JSP +- Отличие Redirect от Forward + +### JSTL +- JSTL +- JSTL для написания JSP страниц + +## Домашнее задание HW15 +- Доделать логику сервлета +- Дополнить отображение и редактирование JSP секциями diff --git a/lesson/lesson17.md b/lesson/lesson17.md new file mode 100644 index 00000000..e2cbc7c8 --- /dev/null +++ b/lesson/lesson17.md @@ -0,0 +1,24 @@ +# Семнадцатое занятие + +### Разбор HW16 + +### Деплой в Heroku +- Deployment with the Heroku CLI + +### Classloader +- Загрузка классов в Java +- Apache Tomcat Class Loader + +## Обзор Java Enterprise +- Из юниоров в разработчики: получаем первую работу +- Java Tools and Technologies Landscape for 2014 +- Java Tools and Technologies Landscape Report 2016 + +#### Spring Pet-Clinic +- Spring PetClinic Sample Application +- Demo +- Presentation + +#### Java Enterprise project Topjava +- Java Enterprise: Вводное занятие +- Demo приложение diff --git a/lesson/lesson2.md b/lesson/lesson2.md new file mode 100644 index 00000000..1e9066ff --- /dev/null +++ b/lesson/lesson2.md @@ -0,0 +1,41 @@ + +# Второе занятие + +## Принципы ООП. +- Методология процедурно-ориентированного и объектно-ориентированного программирования +- Объекты (cостояние, поведение, уникальность) +- Классы. Инкапсуляция. Наследование. Полиморфизм. +- Основы Объектно-Ориентированного Программирования (ООП) +- Типы отношений между классами Наследование, агрегация, композиция, ассоциация. +- Достоинства/Недостатки ООП. Библиотеки vs фреймворки. +- Дополнительно: + - Что такое ООП и с чем его едят? + - Объектно ориентированное программирование + - Николай Алименков — Парадигмы ООП + - Концепции объектно-ориентированного программирования + +### Структура памяти: куча, стек, регистры, константы + - JVM изнутри - оптимизация и профилирование. + - Stack and Heap + - Дополнительно: + - Из каких частей состоит память java процесса. + - Permanent область памяти + - Java thread stack + - Размер Java объектов + +### Типы данных. Пакеты. + - Типы данных + - Классы- оберки + - Ссылочные типы + - Пакеты + - Модификаторы доступа. Область Видимости. + +## Домашнее задание + +> Правка к видео: ArrayStorage.delete() - вместо `storage[i] = null` нужно `storage[size-1] = null` + +- Прочитать Соглашения по именованию. +- Реализовать `ArrayStorage.update` +- Сделать проверки: в `update/delete/get` - резюме есть в storage, в `save`- нет в storage: `System.out.println("Resume ...")`. +- Сделать в save проверку на переполнениеe: `System.out.println("...")`. +- Избавится от дублирования в коде `ArrayStorage` diff --git a/lesson/lesson3.md b/lesson/lesson3.md new file mode 100644 index 00000000..36b8407f --- /dev/null +++ b/lesson/lesson3.md @@ -0,0 +1,24 @@ + +# Третье занятие + +## Разбор Домашнего Задания-2 + +## Объектная модель в Java +- static +- Object. Контракт equals/hashCode +- Интерфейсы +- Полиморфизм, abstract +- [Java Core. Вопросы к собеседованию](http://info.javarush.ru/translation/2014/02/12/Java-Core-Вопросы-к-собеседованию-ч-1.html) + +## Сложность алгоритмов +- Алгоритмы и структуры данных для начинающих: сложность алгоритмов +- Time complexity +- Временная сложность алгоритма +- Вычислительная сложность + +## Паттерн проектирования Шаблонный метод +- Шаблонный метод + +## Домашнее задание +- Закончить реализацию `AbstractArrayStorage`, `ArrayStorage`, `SortedArrayStorage` (`SortedArrayStorage` хранит элементы отсортированными, сортировать весь массив не надо). +- Сделать проверку `ArrayStorage.update` diff --git a/lesson/lesson4.md b/lesson/lesson4.md new file mode 100644 index 00000000..4207304b --- /dev/null +++ b/lesson/lesson4.md @@ -0,0 +1,28 @@ + +# Четвертое занятие + +## Разбор Домашнего Задания-3 + +## Работа со строками. +- Строки в Java. Кодировка. +- Управление строками, функции для работы со строками в Java. +- StringBuilder vs StringBuffer +- String literal pool + +## Исключения + - Исключения (Exceptions). + - "Java. Эффективное программирование" Джошуа Блох: Исключения. + - Конструктор. this, super + +![image](https://cloud.githubusercontent.com/assets/18701152/15581283/4c2f5348-2374-11e6-8fd2-e4de02d2c389.png) + +## Reflection. Аннотации. Модульное тестирование + - Аннотации + - Введение в Java Reflection API + - Модульное тестирование JUnit 4 + - Тестирование с помощью JUnit (Test Case) + + +## Домашнее задание +Реализовать `AbstractStorageTest` и тесты `ArrayStorageTest` и `SortedArrayStorageTest`. +В `MainReflection` сделать вызов метода `toString` через отражение. diff --git a/lesson/lesson5.md b/lesson/lesson5.md new file mode 100644 index 00000000..169a361c --- /dev/null +++ b/lesson/lesson5.md @@ -0,0 +1,15 @@ + +# Пятое занятие + +## Разбор Домашнего Задания-4 + +## Контейнеры/коллекции. +- List, Set, Map, Queue, Iterator, ListIterator +- Структуры данных в картинках +- Инициализация полей в Java +- Java собеседование по коллекциям +- [Часто задаваемые на собеседованиях вопросы по классам коллекциям в Java](http://info.javarush.ru/translation/2013/10/08/Часто-задаваемые-на-собеседованиях-вопросы-по-классам-коллекциям-в-Java-Часть-2-.html#1) +- [Собеседование по Java — коллекции](http://javastudy.ru/interview/collections/) + +## Домашнее задание +Выделить общий класс `AbstractStorage` и реализовать подклассы `ListStorage` и `MapStorage`. Выбор реализации List и Map за вами. diff --git a/lesson/lesson6.md b/lesson/lesson6.md new file mode 100644 index 00000000..3295fbb7 --- /dev/null +++ b/lesson/lesson6.md @@ -0,0 +1,20 @@ + +# Шестое занятие + +## Разбор Домашнего Задания-5 +- Преобразования Integer и int + +## Iterator / Iterable. Вложенные, внутренние, локальные и анонимные классы. +- Iterator / Iterable. +- Вложенные и внутренние классы. Примеры в Collections API: Arrays.asList, ArrayList.iterator +- Локальные и анонимные классы. Comparator + +## Новое в Java 8. +- Lambda выражения. Default методы для Interface. +- Встроенные функциональные интерфейсы. + +## Домашнее задание +- Сделать рефакторинг тестов: `saveOverflow` должно быть только для Array реализаций. +- Рефакторинг: в конструктор Resume добавить второй параметр `fullName` +- Сделать рефакторинг всех реализаций `Storage`: заменить метод `Resume[] getAll()` на `List getAllSorted()` +- Реализовать до конца `MapUuidStorage`. Подумать что еще может быть search key в реализации на основе Map. diff --git a/lesson/lesson7.md b/lesson/lesson7.md new file mode 100644 index 00000000..30494c95 --- /dev/null +++ b/lesson/lesson7.md @@ -0,0 +1,46 @@ + +# Седьмое занятие + +## [Разбор Домашнего Задания-6](lesson6.md#Домашнее-задание) + +## Параметризация. Стирание типов. +- Дженерики (Java, обучающая статья) +- Обобщения (Generic) +- Ограничения. + +## Логирование +- Log4J (Apache logging) +- Java Logging API - Tutorial +- Логирование в Java / quick start +- Ведение лога приложения +- Java Logging: история кошмара + +## Синглетон, Enum +- Одиночка (шаблон проектирования) +- Перечисляемые типы (enum) в Java + +## Домашнее задание: +Доменный объект + +Cделать объектную модель резюме (диаграмма и классы). Образец резюме (делаем упрощенно) + - Делать только классы, включаемые в Resume. Resume - главный класс. В него все включается (композиция - строгий вид агрегации). + - Схожие по структуре и функциональности сущности делаем одним классом. + - Модель упрощаем для хранения только необходимой информации для вывода/ редактирования резюме. + - В модели резюме должны быть представлены контакты и следующие разделы: + - PERSONAL("Личные качества") + - OBJECTIVE("Позиция") + - ACHIEVEMENT("Достижения") + - QUALIFICATIONS("Квалификация") + - EXPERIENCE("Опыт работы") + - EDUCATION("Образование") + - В секциях Достижения и Квалификация хранить список строк + - Учесть в классах модели, что обработка резюме (вывод в html, сохранение, чтение) будет сделано следующим образом: +обработка `fullName`, цикл обработки по контактам, цикл обработки по секциям (для секций использовать полиморфизм, как для фигур: круг, квадрат..). +При добавлении/удалении новых видов контактов (например домашний телефон) или разделов изменения в коде (и БД) должны быть минимальны. + +#### Инструменты для рисования: + +- Generate class diagram in IntelliJ IDEA (Help: working with Diagrams) +- Нарисовать и сфотографировать +- Online: www.draw.io +- yEd - Graph Editor diff --git a/lesson/lesson8.md b/lesson/lesson8.md new file mode 100644 index 00000000..d7336ade --- /dev/null +++ b/lesson/lesson8.md @@ -0,0 +1,21 @@ + +# Восьмое занятие + +## Разбор Домашнего Задания-7: объектная модель резюме + +## Работа с датами и временем +- Класс Date, Calendar, TimeZone +- Java – Convert date and time between timezone +- Joda Time library +- Java 8 Date API + +## Работа с файлами и ресурсами. + - File. Работа с файловой системой. + - Работа с ресурсами. Правильно освобождаем ресурсы в Java + - Java 7 try-with-resources + +## Домашнее задание +- Переделать модель резюме: учесть, что на одной работе (в одном учебном заведении) можно работать/ учиться в разные периоды и при этом имя организации не дублируется +- Сделать рекурсивный обход и вывод имени файлов в каталогах и подкаталогах (корневой каталог- ваш проект) +- Заполнить в `AbstractStorageTest` резюме данными +- Реализовать `AbstractFileStorage`, базовый класс для хранения резюме в файлах. diff --git a/lesson/lesson9.md b/lesson/lesson9.md new file mode 100644 index 00000000..de787f63 --- /dev/null +++ b/lesson/lesson9.md @@ -0,0 +1,25 @@ + +# Девятое занятие + +## Разбор Домашнего Задания-8: + +## Ввод/вывод +- Пакет java.io +- Паттерн Декоратор. +- Классы Reader и Writer. + +## Сериализация +- Сериализация объектов (serialization) +- Реализация Storage используя сериализацию. + +## NIO +- NIO Java 7 +- Чтения строк из файла + +## Основы Java 8 Stream API +- Потоки + +## Домашнее задание +- Сделать рекурсивный вывод каталогов с отступом +- Реализовать Storage через java.nio.file.Path. +- Сделать возможным выбор меджу FileStorage и PathStorage для сериализации через ObjectStream. diff --git a/rules.md b/rules.md deleted file mode 100644 index 924965da..00000000 --- a/rules.md +++ /dev/null @@ -1,33 +0,0 @@ -## Правила на курсе BaseJava при проверке ДЗ наставником - -1. Проверка ДЗ проводится в Telegram -1. Все друг с другом общаются на Ты -1. Проверка ДЗ действует 4.5 месяца с момента нажатия вами в личном кабинете кнопки `Принять участие` -1. Взаимодействие с наставником проходит по следующей схеме: - - вы смотрите видеолекции (ссылки на них находятся рядом с иконками логотипа ютуба), изучаете дополнительный материал, выполняете ДЗ - - по мере готовности сообщаете наставнику, что его нужно проверить - - он проверяет и пишет, что требуется исправить - - вы исправляете, он снова проверяет. И так повторяется до тех пор, пока ваше решение не будет соответствовать условию ДЗ и представлению наставника о том, как его нужно выполнить - - если на вашем последнем сообщении наставник ставит 📌, то он его прочитал. Если стоит 🧐, то в данный момент ваше ДЗ на проверке. Если стоит ✔️- ДЗ проверено - - если все верно, то наставник напишет, чтобы вы переходили к следующему уроку -1. Ссылку на свой репозиторий наставнику достаточно скинуть один раз -1. Комментарии к вашему коду будут даваться наставником в краткой форме. Если вам требуется пояснение по какому-то пункту, то задавайте ему дополнительные вопросы для получения более развернутого ответа -1. Переходить к следующему уроку можно после того, как вам об этом сообщит наставник. Не делайте это самостоятельно -1. Для минимизации "простоев" допускается изучение материалов следующего урока, но без просмотра видео Григория, чтобы не раскрывались вопросы реализации ДЗ -1. Максимальное время проверки ДЗ до суток, но как правило раньше -1. Если наставник не проверил ДЗ за указанный срок, то напомните ему о себе (он вас мог случайно пропустить) -1. Доступ к материалам курса у вас остается навсегда -1. Проверка в выходные дни наставника не гарантируется, но возможна -1. Если у вас закончился срок проверок ДЗ, то его можно продлить в личном кабинете (ссылка на него есть в конце любого нашего письма) [на сайте](https://javaops.ru/) - -#### Общие рекомендации -- Учитесь грамотно формулировать свой вопрос: "у меня не работает" может иметь тысячи причин. Пишите больше подробностей, что вы сделали, что конкретно не работает, какие появляются ошибки. Присылайте в чат скрины с этими ошибками -- Учитесь гуглить с первых уроков - это важный навык, который нужно качать -- Перед тем как задать вопрос наставнику сначала погуглите; если в течении 2-3 часов вы не найдете ответ, то опишите подробно свою проблему наставнику - -#### Расписание проверок ДЗ - -[Максим Чимаев](https://t.me/ch1max) -- выходные дни вторник и четверг -- время проверки с 11:00 по 13:00 и с 17:30 по 19:30 (но не позднее 21:00 по мск. времени) -- проверка в выходные дни не гарантируется, но возможна diff --git a/src/ru/javawebinar/basejava/Config.java b/src/ru/javawebinar/basejava/Config.java index e007b2ab..afd920da 100644 --- a/src/ru/javawebinar/basejava/Config.java +++ b/src/ru/javawebinar/basejava/Config.java @@ -6,9 +6,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.HashSet; import java.util.Properties; -import java.util.Set; public class Config { private static final String PROPS = "/resumes.properties"; @@ -16,14 +14,6 @@ public class Config { private final File storageDir; private final Storage storage; - private Set immutableUuids = new HashSet() {{ // for JDK 9+: Set.of("111", "222"); - add("11111111-1111-1111-1111-111111111111"); - add("22222222-2222-2222-2222-222222222222"); - }}; - - public static Config get() { - return INSTANCE; - } private Config() { try (InputStream is = Config.class.getResourceAsStream(PROPS)) { @@ -36,6 +26,10 @@ private Config() { } } + public static Config get() { + return INSTANCE; + } + public File getStorageDir() { return storageDir; } @@ -43,13 +37,4 @@ public File getStorageDir() { public Storage getStorage() { return storage; } - - public boolean isImmutable(String uuids) { - return immutableUuids.contains(uuids); - } - - public void checkImmutable(String uuids) { - if (immutableUuids.contains(uuids)) - throw new RuntimeException("Зарезервированные резюме нельзя менять"); - } } \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/LazySingleton.java b/src/ru/javawebinar/basejava/LazySingleton.java index 223ce3f7..f7cd1003 100644 --- a/src/ru/javawebinar/basejava/LazySingleton.java +++ b/src/ru/javawebinar/basejava/LazySingleton.java @@ -6,10 +6,6 @@ public class LazySingleton { private LazySingleton() { } - private static class LazySingletonHolder { - private static final LazySingleton INSTANCE = new LazySingleton(); - } - public static LazySingleton getInstance() { return LazySingletonHolder.INSTANCE; // if (INSTANCE == null) { @@ -21,4 +17,8 @@ public static LazySingleton getInstance() { // } // return INSTANCE; } + + private static class LazySingletonHolder { + private static final LazySingleton INSTANCE = new LazySingleton(); + } } \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/MainArray.java b/src/ru/javawebinar/basejava/MainArray.java index 9383f3c1..3f3bc538 100644 --- a/src/ru/javawebinar/basejava/MainArray.java +++ b/src/ru/javawebinar/basejava/MainArray.java @@ -19,14 +19,14 @@ public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); Resume r; while (true) { - System.out.print("Введите одну из команд - (list | save fullName | delete uuid | get uuid | update uuid fullName | clear | exit): "); + System.out.print("Введите одну из команд - (list | save fullname | delete uuid | get uuid | update uuid name | clear | exit): "); String[] params = reader.readLine().trim().toLowerCase().split(" "); if (params.length < 1 || params.length > 3) { System.out.println("Неверная команда."); continue; } String param = null; - if (params.length > 1) { + if (params.length == 2) { param = params[1].intern(); } switch (params[0]) { @@ -66,7 +66,7 @@ public static void main(String[] args) throws IOException { } } - static void printAll() { + private static void printAll() { List all = ARRAY_STORAGE.getAllSorted(); System.out.println("----------------------------"); if (all.size() == 0) { diff --git a/src/ru/javawebinar/basejava/MainConcurrency.java b/src/ru/javawebinar/basejava/MainConcurrency.java index ab57affe..36a24b31 100644 --- a/src/ru/javawebinar/basejava/MainConcurrency.java +++ b/src/ru/javawebinar/basejava/MainConcurrency.java @@ -7,15 +7,8 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; -/** - * gkislin - * 29.08.2016 - */ public class MainConcurrency { public static final int THREADS_NUMBER = 10000; - private int counter; - private final AtomicInteger atomicCounter = new AtomicInteger(); - // private static final Object LOCK = new Object(); // private static final Lock lock = new ReentrantLock(); private static final ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); @@ -27,6 +20,8 @@ protected SimpleDateFormat initialValue() { return new SimpleDateFormat(); } }; + private final AtomicInteger atomicCounter = new AtomicInteger(); + private int counter; public static void main(String[] args) throws InterruptedException { System.out.println(Thread.currentThread().getName()); diff --git a/src/ru/javawebinar/basejava/MainDate.java b/src/ru/javawebinar/basejava/MainDate.java index 6e57aa93..aa2d4cc0 100644 --- a/src/ru/javawebinar/basejava/MainDate.java +++ b/src/ru/javawebinar/basejava/MainDate.java @@ -9,10 +9,7 @@ import java.util.Date; import java.util.TimeZone; -/** - * gkislin - * 20.07.2016 - */ + public class MainDate { public static void main(String[] args) { long start = System.currentTimeMillis(); diff --git a/src/ru/javawebinar/basejava/MainDeadlock.java b/src/ru/javawebinar/basejava/MainDeadlock.java new file mode 100644 index 00000000..b99aefa4 --- /dev/null +++ b/src/ru/javawebinar/basejava/MainDeadlock.java @@ -0,0 +1,25 @@ +package ru.javawebinar.basejava; + +public class MainDeadlock { + private static final Object LOCK1 = new Object(); + private static final Object LOCK2 = new Object(); + + public static void main(String[] args) { + thread(LOCK1, LOCK2); + thread(LOCK2, LOCK1); + } + + private static void thread(Object LOCK1, Object LOCK2) { + new Thread(() -> { + synchronized (LOCK1) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (LOCK2) { + } + } + }).start(); + } +} diff --git a/src/ru/javawebinar/basejava/MainFile.java b/src/ru/javawebinar/basejava/MainFile.java index 19ed6728..278ff7bc 100644 --- a/src/ru/javawebinar/basejava/MainFile.java +++ b/src/ru/javawebinar/basejava/MainFile.java @@ -10,7 +10,7 @@ */ public class MainFile { public static void main(String[] args) { - String filePath = ".\\.gitignore"; + String filePath = "./.gitignore"; File file = new File(filePath); try { @@ -35,19 +35,21 @@ public static void main(String[] args) { } printDirectoryDeeply(dir, ""); } - + public static void printDirectoryDeeply(File dir, String offset) { File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isFile()) { - System.out.println(offset + "F: " + file.getName()); + System.out.println(offset + "File: " + file.getName()); } else if (file.isDirectory()) { - System.out.println(offset + "D: " + file.getName()); - printDirectoryDeeply(file, offset + " "); + System.out.println(offset + "Directory: " + file.getName()); + printDirectoryDeeply(file, "------"); } + } + System.out.println(); } } } diff --git a/src/ru/javawebinar/basejava/MainLambda.java b/src/ru/javawebinar/basejava/MainLambda.java new file mode 100644 index 00000000..8abccbe5 --- /dev/null +++ b/src/ru/javawebinar/basejava/MainLambda.java @@ -0,0 +1,25 @@ +package ru.javawebinar.basejava; + +import java.util.ArrayList; +import java.util.List; + +public class MainLambda { + public static void main(String[] args) { + List list = new ArrayList(); + list.add("dsf1"); + list.add("dsf2"); + list.add("dsf3"); + list.add(""); + + String name = "vasa"; + for (String text : list) { + System.out.println(name + text); + } + + list.forEach(text -> System.out.println(name + text)); + + list.forEach(System.out::println); + list.stream().forEach(System.out::println); + } + +} diff --git a/src/ru/javawebinar/basejava/MainReflection.java b/src/ru/javawebinar/basejava/MainReflection.java index 7fa17969..70e65946 100644 --- a/src/ru/javawebinar/basejava/MainReflection.java +++ b/src/ru/javawebinar/basejava/MainReflection.java @@ -4,21 +4,18 @@ 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("Name"); - Class resumeClass = r.getClass(); - Field field = resumeClass.getDeclaredFields()[0]; + Field field = r.getClass().getDeclaredFields()[0]; field.setAccessible(true); System.out.println(field.getName()); System.out.println(field.get(r)); field.set(r, "new_uuid"); + Object resume = r.getClass().getMethod("toString").invoke(r); - Method method = resumeClass.getMethod("toString"); - Object result = method.invoke(r); - System.out.println(result); + System.out.println(resume); } } \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/MainString.java b/src/ru/javawebinar/basejava/MainString.java index ca47c251..db9d45dd 100644 --- a/src/ru/javawebinar/basejava/MainString.java +++ b/src/ru/javawebinar/basejava/MainString.java @@ -16,3 +16,4 @@ public static void main(String[] args) { System.out.println(str1 == str2); } } + diff --git a/src/ru/javawebinar/basejava/MainTestArrayStorage.java b/src/ru/javawebinar/basejava/MainTestArrayStorage.java index 5ea58940..63886cb3 100644 --- a/src/ru/javawebinar/basejava/MainTestArrayStorage.java +++ b/src/ru/javawebinar/basejava/MainTestArrayStorage.java @@ -7,7 +7,7 @@ * Test ru.javawebinar.basejava.storage.ArrayStorage */ public class MainTestArrayStorage { - static final ArrayStorage ARRAY_STORAGE = new ArrayStorage(); + private static final ArrayStorage ARRAY_STORAGE = new ArrayStorage(); public static void main(String[] args) { Resume r1 = new Resume("uuid1"); @@ -32,10 +32,10 @@ public static void main(String[] args) { System.out.println("Size: " + ARRAY_STORAGE.size()); } - static void printAll() { + private 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/TestContacts.java b/src/ru/javawebinar/basejava/TestContacts.java new file mode 100644 index 00000000..e9322493 --- /dev/null +++ b/src/ru/javawebinar/basejava/TestContacts.java @@ -0,0 +1,13 @@ +package ru.javawebinar.basejava; + +import ru.javawebinar.basejava.model.ContactType; + +public class TestContacts { + public static void main(String[] args) { + + for (ContactType type : ContactType.values()) { + System.out.println(type.getTitle()); + } + } + +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/TestSingleton.java b/src/ru/javawebinar/basejava/TestSingleton.java index 0c28439c..bd904312 100644 --- a/src/ru/javawebinar/basejava/TestSingleton.java +++ b/src/ru/javawebinar/basejava/TestSingleton.java @@ -5,6 +5,9 @@ public class TestSingleton { private static TestSingleton instance; + private TestSingleton() { + } + public static TestSingleton getInstance() { if (instance == null) { instance = new TestSingleton(); @@ -12,9 +15,6 @@ public static TestSingleton getInstance() { return instance; } - private TestSingleton() { - } - public static void main(String[] args) { TestSingleton.getInstance().toString(); Singleton instance = Singleton.valueOf("INSTANCE"); @@ -28,4 +28,4 @@ public static void main(String[] args) { public enum Singleton { INSTANCE } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/exception/ExistStorageException.java b/src/ru/javawebinar/basejava/exception/ExistStorageException.java index 33d98be0..4b540dff 100644 --- a/src/ru/javawebinar/basejava/exception/ExistStorageException.java +++ b/src/ru/javawebinar/basejava/exception/ExistStorageException.java @@ -4,4 +4,4 @@ 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 index 8e4dfff5..a6f74585 100644 --- a/src/ru/javawebinar/basejava/exception/NotExistStorageException.java +++ b/src/ru/javawebinar/basejava/exception/NotExistStorageException.java @@ -1,5 +1,6 @@ package ru.javawebinar.basejava.exception; + public class NotExistStorageException extends StorageException { public NotExistStorageException(String uuid) { super("Resume " + uuid + " not exist", uuid); diff --git a/src/ru/javawebinar/basejava/model/ContactType.java b/src/ru/javawebinar/basejava/model/ContactType.java index 989fa64e..5088e421 100644 --- a/src/ru/javawebinar/basejava/model/ContactType.java +++ b/src/ru/javawebinar/basejava/model/ContactType.java @@ -13,12 +13,7 @@ public String toHtml0(String value) { MAIL("Почта") { @Override public String toHtml0(String value) { - return getTitle() + ": " + toLink(value); - } - - @Override - public String toLink(String value) { - return (value == null) ? "" : toLink("mailto:" + value, value); + return getTitle() + ": " + toLink("mailto:" + value, value); } }, LINKEDIN("Профиль LinkedIn") { @@ -52,6 +47,10 @@ public String toHtml0(String value) { this.title = title; } + public static String toLink(String href, String title) { + return "" + title + ""; + } + public String getTitle() { return title; } @@ -67,8 +66,4 @@ public String toHtml(String value) { public String toLink(String href) { return toLink(href, title); } - - public static String toLink(String href, String title) { - return "" + title + ""; - } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/model/ListSection.java b/src/ru/javawebinar/basejava/model/ListSection.java index 9c107926..4db47f0a 100644 --- a/src/ru/javawebinar/basejava/model/ListSection.java +++ b/src/ru/javawebinar/basejava/model/ListSection.java @@ -11,7 +11,6 @@ public class ListSection extends Section { private static final long serialVersionUID = 1L; - public static final ListSection EMPTY = new ListSection(""); private List items; diff --git a/src/ru/javawebinar/basejava/model/OrganizationSection.java b/src/ru/javawebinar/basejava/model/OrganizationSection.java index 16cf0060..e9a8a458 100644 --- a/src/ru/javawebinar/basejava/model/OrganizationSection.java +++ b/src/ru/javawebinar/basejava/model/OrganizationSection.java @@ -16,7 +16,8 @@ public class OrganizationSection extends Section { private List organizations; - public OrganizationSection() {} + public OrganizationSection() { + } public OrganizationSection(Organization... organizations) { this(Arrays.asList(organizations)); diff --git a/src/ru/javawebinar/basejava/model/Resume.java b/src/ru/javawebinar/basejava/model/Resume.java index 2124bdbc..c8fafd85 100644 --- a/src/ru/javawebinar/basejava/model/Resume.java +++ b/src/ru/javawebinar/basejava/model/Resume.java @@ -13,7 +13,6 @@ @XmlAccessorType(XmlAccessType.FIELD) public class Resume implements Comparable, Serializable { private static final long serialVersionUID = 1L; - public static final Resume EMPTY = new Resume(); static { @@ -25,14 +24,12 @@ public class Resume implements Comparable, Serializable { EMPTY.setSection(SectionType.EDUCATION, new OrganizationSection(Organization.EMPTY)); } + private final Map contacts = new EnumMap<>(ContactType.class); + private final Map sections = new EnumMap<>(SectionType.class); // Unique identifier private String uuid; - private String fullName; - private final Map contacts = new EnumMap<>(ContactType.class); - private final Map sections = new EnumMap<>(SectionType.class); - public Resume() { } diff --git a/src/ru/javawebinar/basejava/model/SectionType.java b/src/ru/javawebinar/basejava/model/SectionType.java index 820fe6fb..06b3b891 100644 --- a/src/ru/javawebinar/basejava/model/SectionType.java +++ b/src/ru/javawebinar/basejava/model/SectionType.java @@ -17,5 +17,4 @@ public enum SectionType { public String getTitle() { return title; } -} - +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/model/TextSection.java b/src/ru/javawebinar/basejava/model/TextSection.java index faa2c376..a8e0d6fe 100644 --- a/src/ru/javawebinar/basejava/model/TextSection.java +++ b/src/ru/javawebinar/basejava/model/TextSection.java @@ -5,7 +5,6 @@ public class TextSection extends Section { private static final long serialVersionUID = 1L; - public static final TextSection EMPTY = new TextSection(""); private String content; diff --git a/src/ru/javawebinar/basejava/sql/ConnectionFactory.java b/src/ru/javawebinar/basejava/sql/ConnectionFactory.java index b6e4f0d7..64297d5b 100644 --- a/src/ru/javawebinar/basejava/sql/ConnectionFactory.java +++ b/src/ru/javawebinar/basejava/sql/ConnectionFactory.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.sql.SQLException; +@FunctionalInterface public interface ConnectionFactory { Connection getConnection() throws SQLException; } diff --git a/src/ru/javawebinar/basejava/sql/SqlExecutor.java b/src/ru/javawebinar/basejava/sql/SqlExecutor.java index 5d6d0848..5e79a624 100644 --- a/src/ru/javawebinar/basejava/sql/SqlExecutor.java +++ b/src/ru/javawebinar/basejava/sql/SqlExecutor.java @@ -5,4 +5,4 @@ public interface SqlExecutor { T execute(PreparedStatement st) throws SQLException; -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/sql/SqlTransaction.java b/src/ru/javawebinar/basejava/sql/SqlTransaction.java index bdc04431..8d4c2bc5 100644 --- a/src/ru/javawebinar/basejava/sql/SqlTransaction.java +++ b/src/ru/javawebinar/basejava/sql/SqlTransaction.java @@ -5,4 +5,4 @@ public interface SqlTransaction { T execute(Connection conn) throws SQLException; -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java b/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java index b351818f..b0d0f07c 100644 --- a/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java +++ b/src/ru/javawebinar/basejava/storage/AbstractArrayStorage.java @@ -10,7 +10,7 @@ * Array based storage for Resumes */ public abstract class AbstractArrayStorage extends AbstractStorage { - protected static final int STORAGE_LIMIT = 10000; + static final int STORAGE_LIMIT = 10; protected Resume[] storage = new Resume[STORAGE_LIMIT]; protected int size = 0; @@ -29,16 +29,14 @@ protected void doUpdate(Resume r, Integer index) { storage[index] = r; } - /** - * @return array, contains only Resumes in storage (without null) - */ @Override public List doCopyAll() { return Arrays.asList(Arrays.copyOfRange(storage, 0, size)); } + @Override - protected void doSave(Resume r, Integer index) { + public void doSave(Resume r, Integer index) { if (size == STORAGE_LIMIT) { throw new StorageException("Storage overflow", r.getUuid()); } else { diff --git a/src/ru/javawebinar/basejava/storage/AbstractStorage.java b/src/ru/javawebinar/basejava/storage/AbstractStorage.java index 9ab920fc..a203b0ed 100644 --- a/src/ru/javawebinar/basejava/storage/AbstractStorage.java +++ b/src/ru/javawebinar/basejava/storage/AbstractStorage.java @@ -9,8 +9,6 @@ import java.util.logging.Logger; public abstract class AbstractStorage implements Storage { - - // protected final Logger LOG = Logger.getLogger(getClass().getName()); private static final Logger LOG = Logger.getLogger(AbstractStorage.class.getName()); protected abstract SK getSearchKey(String uuid); @@ -52,24 +50,23 @@ public Resume get(String uuid) { } private SK getExistedSearchKey(String uuid) { + LOG.warning("Resume " + uuid + " not exist"); SK searchKey = getSearchKey(uuid); if (!isExist(searchKey)) { - LOG.warning("Resume " + uuid + " not exist"); throw new NotExistStorageException(uuid); } return searchKey; } private SK getNotExistedSearchKey(String uuid) { + LOG.warning("Resume " + uuid + " already exist"); SK searchKey = getSearchKey(uuid); if (isExist(searchKey)) { - LOG.warning("Resume " + uuid + " already exist"); throw new ExistStorageException(uuid); } return searchKey; } - @Override public List getAllSorted() { LOG.info("getAllSorted"); List list = doCopyAll(); diff --git a/src/ru/javawebinar/basejava/storage/ArrayStorage.java b/src/ru/javawebinar/basejava/storage/ArrayStorage.java index 7a254681..71c93ace 100644 --- a/src/ru/javawebinar/basejava/storage/ArrayStorage.java +++ b/src/ru/javawebinar/basejava/storage/ArrayStorage.java @@ -17,6 +17,7 @@ protected void insertElement(Resume r, int index) { storage[size] = r; } + protected Integer getSearchKey(String uuid) { for (int i = 0; i < size; i++) { if (uuid.equals(storage[i].getUuid())) { @@ -25,4 +26,4 @@ protected Integer getSearchKey(String uuid) { } return -1; } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/ListStorage.java b/src/ru/javawebinar/basejava/storage/ListStorage.java index cbc39530..aedcedd2 100644 --- a/src/ru/javawebinar/basejava/storage/ListStorage.java +++ b/src/ru/javawebinar/basejava/storage/ListStorage.java @@ -40,7 +40,7 @@ protected Resume doGet(Integer searchKey) { @Override protected void doDelete(Integer searchKey) { - list.remove(searchKey.intValue()); + list.remove((searchKey).intValue()); } @Override @@ -57,4 +57,4 @@ public List doCopyAll() { public int size() { return list.size(); } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/MapResumeStorage.java b/src/ru/javawebinar/basejava/storage/MapResumeStorage.java index 27137eef..97b58527 100644 --- a/src/ru/javawebinar/basejava/storage/MapResumeStorage.java +++ b/src/ru/javawebinar/basejava/storage/MapResumeStorage.java @@ -16,28 +16,28 @@ protected Resume getSearchKey(String uuid) { } @Override - protected void doUpdate(Resume r, Resume resume) { - map.put(r.getUuid(), r); + protected void doUpdate(Resume r, Resume searchKey) { + doSave(r, searchKey); } @Override - protected boolean isExist(Resume resume) { - return resume != null; + protected boolean isExist(Resume searchKey) { + return searchKey != null; } @Override - protected void doSave(Resume r, Resume resume) { + protected void doSave(Resume r, Resume searchKey) { map.put(r.getUuid(), r); } @Override - protected Resume doGet(Resume resume) { - return resume; + protected Resume doGet(Resume searchKey) { + return searchKey; } @Override - protected void doDelete(Resume resume) { - map.remove(resume.getUuid()); + protected void doDelete(Resume searchKey) { + map.remove((searchKey).getUuid()); } @Override @@ -46,7 +46,7 @@ public void clear() { } @Override - public List doCopyAll() { + protected List doCopyAll() { return new ArrayList<>(map.values()); } diff --git a/src/ru/javawebinar/basejava/storage/MapUuidStorage.java b/src/ru/javawebinar/basejava/storage/MapUuidStorage.java index b35b32fd..7eb28a24 100644 --- a/src/ru/javawebinar/basejava/storage/MapUuidStorage.java +++ b/src/ru/javawebinar/basejava/storage/MapUuidStorage.java @@ -2,7 +2,10 @@ import ru.javawebinar.basejava.model.Resume; -import java.util.*; +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<>(); @@ -14,7 +17,7 @@ protected String getSearchKey(String uuid) { @Override protected void doUpdate(Resume r, String uuid) { - map.put(uuid, r); + doSave(r, uuid); } @Override @@ -43,7 +46,7 @@ public void clear() { } @Override - public List doCopyAll() { + protected List doCopyAll() { return new ArrayList<>(map.values()); } diff --git a/src/ru/javawebinar/basejava/storage/SortedArrayStorage.java b/src/ru/javawebinar/basejava/storage/SortedArrayStorage.java index 9b7502e9..cb687e5d 100644 --- a/src/ru/javawebinar/basejava/storage/SortedArrayStorage.java +++ b/src/ru/javawebinar/basejava/storage/SortedArrayStorage.java @@ -6,16 +6,8 @@ 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 = (o1, o2) -> o1.getUuid().compareTo(o2.getUuid()); + static final Comparator RESUME_COMPARATOR = Comparator.comparing(Resume::getUuid); @Override protected void fillDeletedElement(int index) { @@ -35,7 +27,7 @@ protected void insertElement(Resume r, int index) { @Override protected Integer getSearchKey(String uuid) { - Resume searchKey = new Resume(uuid, "dummy"); + Resume searchKey = new Resume(uuid, "Vasa"); return Arrays.binarySearch(storage, 0, size, searchKey, RESUME_COMPARATOR); } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/SqlStorage.java b/src/ru/javawebinar/basejava/storage/SqlStorage.java index 32d7a479..87876368 100644 --- a/src/ru/javawebinar/basejava/storage/SqlStorage.java +++ b/src/ru/javawebinar/basejava/storage/SqlStorage.java @@ -203,4 +203,4 @@ private void addSection(ResultSet rs, Resume r) throws SQLException { r.setSection(type, JsonParser.read(content, Section.class)); } } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/Storage.java b/src/ru/javawebinar/basejava/storage/Storage.java index 8472c148..a9cc6ec0 100644 --- a/src/ru/javawebinar/basejava/storage/Storage.java +++ b/src/ru/javawebinar/basejava/storage/Storage.java @@ -6,20 +6,17 @@ public interface Storage { + int size(); + 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) - */ - List getAllSorted(); + Resume get(String uuid); - int size(); -} + List getAllSorted(); +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/storage/serializer/DataStreamSerializer.java b/src/ru/javawebinar/basejava/storage/serializer/DataStreamSerializer.java index 8ed7deae..bfaa645c 100644 --- a/src/ru/javawebinar/basejava/storage/serializer/DataStreamSerializer.java +++ b/src/ru/javawebinar/basejava/storage/serializer/DataStreamSerializer.java @@ -108,18 +108,6 @@ private List readList(DataInputStream dis, ElementReader reader) throw return list; } - private interface ElementProcessor { - void process() throws IOException; - } - - private interface ElementReader { - T read() throws IOException; - } - - private interface ElementWriter { - void write(T t) throws IOException; - } - private void readItems(DataInputStream dis, ElementProcessor processor) throws IOException { int size = dis.readInt(); for (int i = 0; i < size; i++) { @@ -133,4 +121,16 @@ private void writeCollection(DataOutputStream dos, Collection collection, writer.write(item); } } + + private interface ElementProcessor { + void process() throws IOException; + } + + private interface ElementReader { + T read() throws IOException; + } + + private interface ElementWriter { + void write(T t) throws IOException; + } } \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/util/DateUtil.java b/src/ru/javawebinar/basejava/util/DateUtil.java index 45a325e7..85a92d14 100644 --- a/src/ru/javawebinar/basejava/util/DateUtil.java +++ b/src/ru/javawebinar/basejava/util/DateUtil.java @@ -5,10 +5,6 @@ import java.time.YearMonth; import java.time.format.DateTimeFormatter; -/** - * gkislin - * 20.07.2016 - */ public class DateUtil { public static final LocalDate NOW = LocalDate.of(3000, 1, 1); @@ -28,4 +24,4 @@ public static LocalDate parse(String date) { YearMonth yearMonth = YearMonth.parse(date, DATE_FORMATTER); return LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1); } -} \ No newline at end of file +} diff --git a/src/ru/javawebinar/basejava/util/HtmlUtil.java b/src/ru/javawebinar/basejava/util/HtmlUtil.java index d3dccba5..54898f16 100644 --- a/src/ru/javawebinar/basejava/util/HtmlUtil.java +++ b/src/ru/javawebinar/basejava/util/HtmlUtil.java @@ -1,3 +1,4 @@ + package ru.javawebinar.basejava.util; import ru.javawebinar.basejava.model.Organization; @@ -11,4 +12,4 @@ public static String formatDates(Organization.Position position) { return DateUtil.format(position.getStartDate()) + " - " + DateUtil.format(position.getEndDate()); } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/util/LocalDateAdapter.java b/src/ru/javawebinar/basejava/util/LocalDateAdapter.java index 3f22b250..6e7782d8 100644 --- a/src/ru/javawebinar/basejava/util/LocalDateAdapter.java +++ b/src/ru/javawebinar/basejava/util/LocalDateAdapter.java @@ -13,4 +13,4 @@ public LocalDate unmarshal(String str) throws Exception { public String marshal(LocalDate ld) throws Exception { return ld.toString(); } -} +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/util/XmlParser.java b/src/ru/javawebinar/basejava/util/XmlParser.java index 47fafcea..02e8d54b 100644 --- a/src/ru/javawebinar/basejava/util/XmlParser.java +++ b/src/ru/javawebinar/basejava/util/XmlParser.java @@ -41,5 +41,4 @@ public void marshall(Object instance, Writer writer) { throw new IllegalStateException(e); } } -} - +} \ No newline at end of file diff --git a/src/ru/javawebinar/basejava/web/ResumeServlet.java b/src/ru/javawebinar/basejava/web/ResumeServlet.java index 909b0b1c..afe6089c 100644 --- a/src/ru/javawebinar/basejava/web/ResumeServlet.java +++ b/src/ru/javawebinar/basejava/web/ResumeServlet.java @@ -13,29 +13,19 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; public class ResumeServlet extends HttpServlet { - private enum THEME { - dark, light, purple - } - private Storage storage; // = Config.get().getStorage(); - private final Set themes = new HashSet<>(); // https://stackoverflow.com/a/4936895/548473 @Override public void init(ServletConfig config) throws ServletException { super.init(config); storage = Config.get().getStorage(); - for (THEME t : THEME.values()) { - themes.add(t.name()); - } } - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { request.setCharacterEncoding("UTF-8"); String uuid = request.getParameter("uuid"); String fullName = request.getParameter("fullName"); @@ -45,7 +35,6 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) if (isCreate) { r = new Resume(fullName); } else { - Config.get().checkImmutable(uuid); r = storage.get(uuid); r.setFullName(fullName); } @@ -104,14 +93,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) } else { storage.update(r); } - response.sendRedirect("resume?theme=" + getTheme(request)); + response.sendRedirect("resume"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { String uuid = request.getParameter("uuid"); String action = request.getParameter("action"); - request.setAttribute("theme", getTheme(request)); - if (action == null) { request.setAttribute("resumes", storage.getAllSorted()); request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response); @@ -120,7 +107,6 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t Resume r; switch (action) { case "delete": - Config.get().checkImmutable(uuid); storage.delete(uuid); response.sendRedirect("resume"); return; @@ -174,9 +160,4 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t ("view".equals(action) ? "/WEB-INF/jsp/view.jsp" : "/WEB-INF/jsp/edit.jsp") ).forward(request, response); } - - private String getTheme(HttpServletRequest request) { - String theme = request.getParameter("theme"); - return themes.contains(theme) ? theme : THEME.light.name(); - } -} +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/AbstractArrayStorageTest.java b/test/ru/javawebinar/basejava/storage/AbstractArrayStorageTest.java index 9bd85dd0..f3c14d76 100644 --- a/test/ru/javawebinar/basejava/storage/AbstractArrayStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/AbstractArrayStorageTest.java @@ -5,12 +5,9 @@ import ru.javawebinar.basejava.exception.StorageException; import ru.javawebinar.basejava.model.Resume; -/** - * gkislin - * 12.06.2016 - */ public abstract class AbstractArrayStorageTest extends AbstractStorageTest { - protected AbstractArrayStorageTest(Storage storage) { + + AbstractArrayStorageTest(Storage storage) { super(storage); } @@ -25,4 +22,4 @@ public void saveOverflow() throws Exception { } storage.save(new Resume("Overflow")); } -} \ No newline at end of file +} diff --git a/test/ru/javawebinar/basejava/storage/AbstractStorageTest.java b/test/ru/javawebinar/basejava/storage/AbstractStorageTest.java index 9eefcc7f..895afad1 100644 --- a/test/ru/javawebinar/basejava/storage/AbstractStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/AbstractStorageTest.java @@ -58,7 +58,7 @@ public void update() throws Exception { @Test(expected = NotExistStorageException.class) public void updateNotExist() throws Exception { - storage.update(new Resume("dummy")); + storage.get("dummy"); } @Test diff --git a/test/ru/javawebinar/basejava/storage/ArrayStorageTest.java b/test/ru/javawebinar/basejava/storage/ArrayStorageTest.java index c5903eed..a788c733 100644 --- a/test/ru/javawebinar/basejava/storage/ArrayStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/ArrayStorageTest.java @@ -1,9 +1,7 @@ package ru.javawebinar.basejava.storage; public class ArrayStorageTest extends AbstractArrayStorageTest { - public ArrayStorageTest() { super(new ArrayStorage()); } - -} \ No newline at end of file +} diff --git a/test/ru/javawebinar/basejava/storage/MapResumeStorageTest.java b/test/ru/javawebinar/basejava/storage/MapResumeStorageTest.java index 321aa46e..0e182a17 100644 --- a/test/ru/javawebinar/basejava/storage/MapResumeStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/MapResumeStorageTest.java @@ -1,7 +1,6 @@ package ru.javawebinar.basejava.storage; public class MapResumeStorageTest extends AbstractStorageTest { - public MapResumeStorageTest() { super(new MapResumeStorage()); } diff --git a/test/ru/javawebinar/basejava/storage/MapUuidStorageTest.java b/test/ru/javawebinar/basejava/storage/MapUuidStorageTest.java index 556dc591..99a7643e 100644 --- a/test/ru/javawebinar/basejava/storage/MapUuidStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/MapUuidStorageTest.java @@ -1,8 +1,7 @@ package ru.javawebinar.basejava.storage; public class MapUuidStorageTest extends AbstractStorageTest { - public MapUuidStorageTest() { super(new MapUuidStorage()); } -} +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/SortedArrayStorageTest.java b/test/ru/javawebinar/basejava/storage/SortedArrayStorageTest.java index dbad3bd1..80a89ea2 100644 --- a/test/ru/javawebinar/basejava/storage/SortedArrayStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/SortedArrayStorageTest.java @@ -1,8 +1,7 @@ package ru.javawebinar.basejava.storage; public class SortedArrayStorageTest extends AbstractArrayStorageTest { - public SortedArrayStorageTest() { super(new SortedArrayStorage()); } -} +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/SqlStorageTest.java b/test/ru/javawebinar/basejava/storage/SqlStorageTest.java index afc89c0d..bd789191 100644 --- a/test/ru/javawebinar/basejava/storage/SqlStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/SqlStorageTest.java @@ -2,13 +2,9 @@ import ru.javawebinar.basejava.Config; -/** - * gkislin - * 23.06.2016 - */ public class SqlStorageTest extends AbstractStorageTest { public SqlStorageTest() { super(Config.get().getStorage()); } -} +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/storage/XmlPathStorageTest.java b/test/ru/javawebinar/basejava/storage/XmlPathStorageTest.java index b3d7a431..e7851f35 100644 --- a/test/ru/javawebinar/basejava/storage/XmlPathStorageTest.java +++ b/test/ru/javawebinar/basejava/storage/XmlPathStorageTest.java @@ -7,4 +7,4 @@ public class XmlPathStorageTest extends AbstractStorageTest { public XmlPathStorageTest() { super(new PathStorage(STORAGE_DIR.getAbsolutePath(), new XmlStreamSerializer())); } -} +} \ No newline at end of file diff --git a/test/ru/javawebinar/basejava/util/JsonParserTest.java b/test/ru/javawebinar/basejava/util/JsonParserTest.java index 1af6828e..6d077843 100644 --- a/test/ru/javawebinar/basejava/util/JsonParserTest.java +++ b/test/ru/javawebinar/basejava/util/JsonParserTest.java @@ -25,4 +25,4 @@ public void write() throws Exception { Section section2 = JsonParser.read(json, Section.class); Assert.assertEquals(section1, section2); } -} +} \ No newline at end of file diff --git a/web/WEB-INF/jsp/edit.jsp b/web/WEB-INF/jsp/edit.jsp index 9242aa01..88a98e3f 100644 --- a/web/WEB-INF/jsp/edit.jsp +++ b/web/WEB-INF/jsp/edit.jsp @@ -3,104 +3,96 @@ <%@ page import="ru.javawebinar.basejava.model.OrganizationSection" %> <%@ page import="ru.javawebinar.basejava.model.SectionType" %> <%@ page import="ru.javawebinar.basejava.util.DateUtil" %> -<%@ page import="ru.javawebinar.basejava.Config" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - - - + Резюме ${resume.fullName} -
- - -
-
-
ФИО
- - -
Контакты
- - - - - -
- -
Секции
- - - - -
${type.title}
- - - - - - - - - - - - - -
-
-
- -<%-- --%> - - - - -<%-- --%> - +
+ + +

Имя:

+
+ +
+

Контакты:

+ +
+
${type.title}
+
+
+
+
+ + + +

${type.title}

+ + + + + + + + + + + + +
+
Название учереждения:
+
+
+
+
Сайт учереждения:
+
+ +
+
+
- -
- - -
- - - - +
+
Начальная дата:
+
+ +
+
+
+
Конечная дата:
+
+ +
+
+
Должность:
+
+
+
+
Описание:
+
+
- - - - - -
- -
- - - - -
- -
-
- +
+ + + + + + + + diff --git a/web/WEB-INF/jsp/fragments/footer.jsp b/web/WEB-INF/jsp/fragments/footer.jsp index bcfbdb4e..ba7048e4 100644 --- a/web/WEB-INF/jsp/fragments/footer.jsp +++ b/web/WEB-INF/jsp/fragments/footer.jsp @@ -1,6 +1,4 @@ <%@page contentType="text/html" pageEncoding="UTF-8" %> - + diff --git a/web/WEB-INF/jsp/fragments/header.jsp b/web/WEB-INF/jsp/fragments/header.jsp index 22ba67be..81e03b21 100644 --- a/web/WEB-INF/jsp/fragments/header.jsp +++ b/web/WEB-INF/jsp/fragments/header.jsp @@ -1,11 +1,3 @@ <%@page contentType="text/html" pageEncoding="UTF-8" %> - +
Управление резюме
+
\ No newline at end of file diff --git a/web/WEB-INF/jsp/list.jsp b/web/WEB-INF/jsp/list.jsp index aa8f620b..e0f9c03d 100644 --- a/web/WEB-INF/jsp/list.jsp +++ b/web/WEB-INF/jsp/list.jsp @@ -1,76 +1,41 @@ <%@ page import="ru.javawebinar.basejava.model.ContactType" %> -<%@ page import="ru.javawebinar.basejava.Config" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - - - + Список всех резюме -
-
Тема
-
-
- -
-
-
-
-
- -
- - - - - - - - - - - - - - - - -
ИмяКонтактыРедактироватьУдалить
- ${resume.fullName} - - <%=ContactType.MAIL.toLink(resume.getContact(ContactType.MAIL))%> - - - - - - - - - - -
-
-
-
+
+ + + + + + + + + + + + + + + + + + + + + + +
ИмяEmail
Новое резюме
${resume.fullName}<%=ContactType.MAIL.toHtml(resume.getContact(ContactType.MAIL))%> +
+
- + \ No newline at end of file diff --git a/web/WEB-INF/jsp/view.jsp b/web/WEB-INF/jsp/view.jsp index 19c051d7..24de46e2 100644 --- a/web/WEB-INF/jsp/view.jsp +++ b/web/WEB-INF/jsp/view.jsp @@ -7,94 +7,89 @@ - - - + Резюме ${resume.fullName} - -
-
-
${resume.fullName} - - - -
-
- - - -
<%=contactEntry.getKey().toHtml(contactEntry.getValue())%> -
-
-
- -
- +
+

${resume.fullName} 

+

+ + + <%=contactEntry.getKey().toHtml(contactEntry.getValue())%>
+
+

+


+ -
${type.title}
+
+ + -
<%=((TextSection) section).getContent()%> -
+
+ + -
<%=((TextSection) section).getContent()%> -
+
+ + -
    - -
  • ${item}
  • -
    -
+
+ + -
- - -
${org.homePage.name}
-
- - - -
- - -
-
<%=HtmlUtil.formatDates(position)%> -
-
${position.title}
-
+
+ + + + + + + + + - - - - +

${type.title}

+

<%=((TextSection) section).getContent()%> +

+
+ <%=((TextSection) section).getContent()%> +
+
    + +
  • ${item}
  • +
    +
+
- + +

${org.homePage.name}

-
${position.description}
+

${org.homePage.name}

- - +
<%=HtmlUtil.formatDates(position)%> + ${position.title}
${position.description}
+
+ +
- - + \ No newline at end of file diff --git a/web/WEB-INF/web.xml b/web/WEB-INF/web.xml index a82224ad..eccd76cb 100644 --- a/web/WEB-INF/web.xml +++ b/web/WEB-INF/web.xml @@ -1,9 +1,8 @@ - - resumeServlet ru.javawebinar.basejava.web.ResumeServlet @@ -12,5 +11,4 @@ resumeServlet /resume - \ No newline at end of file diff --git a/web/css/edit-resume-styles.css b/web/css/edit-resume-styles.css deleted file mode 100644 index cd4f817a..00000000 --- a/web/css/edit-resume-styles.css +++ /dev/null @@ -1,173 +0,0 @@ -input, textarea { - height: 60px; - width: 100%; - - background: var(--input-field-background); - border: 0; - border-radius: 10px; - box-shadow: 0 0 50px 0 var(--input-field-shadow) inset; - padding: 0 25px 0 25px; - margin: 20px 0 0 0; -} - -input:focus, input:focus-visible, -textarea:focus, textarea:focus-visible { - outline: none !important; - border-color: var(--input-field-background); - box-shadow: 0 0 10px var(--input-field-shadow); -} - -input::placeholder, textarea::placeholder { - font-weight: normal; - font-size: 14px; - line-height: 19px; - - color: var(--text-color); - opacity: 0.5; -} - -textarea { - height: 40px; - padding-top: 20px; -} - -button { - font-family: Open Sans, serif; - font-style: normal; - font-weight: 600; - font-size: 14px; - line-height: 19px; - - align-items: center; - - height: 60px; - margin: 20px 0 10px 0; - - box-sizing: border-box; - border-radius: 10px; -} - -.form-wrapper { - font-family: Open Sans, serif; - font-style: normal; - font-weight: 600; - color: var(--text-color); - - height: 100%; - min-width: 610px; - width: 50%; - margin: 0 0 0 25%; - display: block; -} - -.section { - font-size: 32px; - line-height: 44px; - - margin: 50px 0 0 0; -} - -.field { - min-height: 60px; - color: var(--text-color); -} - -.field-label { - font-size: 24px; - line-height: 33px; - - margin: 40px 0 0 0; -} - -.spacer { - width: 100%; - min-width: 100%; - height: 2px; - margin: 40px 0 10px 0; - - background: var(--spacer-background); - border-radius: 10px; -} - -.date-section { - display: block; -} - -.date { - width: 250px; -} - -.date-margin { - margin-left: 10px; -} - -.green-button { - width: 295px; - margin: 20px 0 10px 0; - - color: var(--submit-button-color); - - border: 2px solid var(--submit-button-color); - background: var(--submit-button-background); -} - -.green-button:hover { - opacity: 0.8; - box-shadow: 0 0 10px var(--submit-button-color); -} - -.small-green-button { - height: 50px; - width: 200px; - margin: 20px 0 0 0; - - color: var(--submit-button-color); - - border: 2px solid var(--submit-button-color); - background: var(--submit-button-background); -} - -.green-button:hover, .small-green-button:hover { - opacity: 0.8; - box-shadow: 0 0 10px var(--submit-button-color); -} - -.button-section { - width: 100%; - margin: 40px 0 90px 0; - display: inline-flex; -} - -.red-cancel-button { - width: 100%; - margin-right: 10px; - - color: var(--button-text-color); - - border: 2px solid var(--cancel-button-color); - background: var(--cancel-button-color); -} - -.red-cancel-button:hover { - color: var(--cancel-button-color); - opacity: 0.8; - box-shadow: 0 0 10px var(--cancel-button-color); - background: var(--button-text-color); -} - -.green-submit-button { - width: 100%; - margin-left: 10px; - - color: var(--button-text-color); - - border: 2px solid var(--save-button-background); - background: var(--save-button-background); -} - -.green-submit-button:hover { - color: var(--save-button-background); - opacity: 0.8; - box-shadow: 0 0 10px var(--save-button-background); - background: var(--button-text-color); -} \ No newline at end of file diff --git a/web/css/resume-list-styles.css b/web/css/resume-list-styles.css deleted file mode 100644 index 87ec92ad..00000000 --- a/web/css/resume-list-styles.css +++ /dev/null @@ -1,108 +0,0 @@ -table { - width: 100%; - border-spacing: 0; - text-align: center; - box-shadow: 0 0 50px var(--table-shadow-color); -} - -.table-wrapper { - height: 100%; - min-width: 610px; - width: 50%; - margin: 0 0 0 25%; - display: block; -} - -.add-resume { - height: 100px; - width: 100%; - display: inline-flex; - align-items: center; - justify-content: end; -} - -.add-resume-title { - font-family: Roboto, serif; - font-style: normal; - font-weight: bold; - font-size: 15px; - - width: 70px; - margin-left: 13px; - display: block; - - color: var(--add-resume-text-color); -} - -.resumes-list { - width: 100%; -} - -.resumes-list img { - height: 20px; -} - -.t-header, tr { - font-family: Roboto, serif; - font-style: normal; - font-weight: bold; - font-size: 16px; - line-height: 19px; - - height: 70px; - - color: var(--table-header-text-color); - background: var(--table-header-background); -} - -.t-body, tr { - font-family: Open Sans, serif; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 19px; - - color: var(--table-text-color); -} - -.t-body, tr:nth-child(odd) { - height: 70px; - background: var(--table-odd-row-background); -} - -.t-body, tr:nth-child(even) { - height: 90px; - background: var(--table-even-row-background); -} - -.resumes-list th:first-of-type { - border-top-left-radius: 10px; -} - -.resumes-list th:last-of-type { - border-top-right-radius: 10px; -} - -.resumes-list tr:last-of-type td:first-of-type { - border-bottom-left-radius: 10px; -} - -.resumes-list tr:last-of-type td:last-of-type { - border-bottom-right-radius: 10px; -} - -.name-column { - text-align: start; - padding: 0 0 0 38px; -} - -.info-column { - text-align: start; - width: 230px !important; - min-width: 180px !important; -} - -.img-column { - width: 110px !important; - min-width: 110px !important; -} \ No newline at end of file diff --git a/web/css/style.css b/web/css/style.css new file mode 100644 index 00000000..90b58df8 --- /dev/null +++ b/web/css/style.css @@ -0,0 +1,71 @@ +section { + width: 900px; + margin: auto; +} + +header { + background: none repeat scroll 0 0 #A6C9E2; + color: #2E6E9E; + font-size: 20px; + padding: 5px 20px; + text-align: center; +} + +footer { + background: none repeat scroll 0 0 #A6C9E2; + color: #2E6E9E; + font-size: 20px; + padding: 5px 20px; + margin: 20px 0; + text-align: center; +} + +dl { + background: none repeat scroll 0 0 #FAFAFA; + margin: 8px 0; + padding: 0; +} + +dt { + display: inline-block; + width: 170px; +} + +dd { + display: inline-block; + margin-left: 8px; + vertical-align: top; +} + +h2, h3 { + margin: 15px 0 5px; +} + +li { + margin: 15px 0; +} + +a[href^="skype:"] { + padding-left: 20px !important; + background: url(../img/skype.png) no-repeat center left; +} + +a[href^="mailto:"] { + padding-left: 20px !important; + background: url(../img/email.png) no-repeat center left; +} + +a[href^="https://stackoverflow.com"] { + padding-left: 20px !important; + background: url(../img/so.png) no-repeat center left; +} + +a[href^="https://www.linkedin.com"] { + padding-left: 20px !important; + background: url(../img/lin.png) no-repeat center left; +} + +a[href*="github."] { + padding-left: 20px !important; + background: url(../img/gh.png) no-repeat center left; +} \ No newline at end of file diff --git a/web/css/styles.css b/web/css/styles.css deleted file mode 100644 index fc9b712d..00000000 --- a/web/css/styles.css +++ /dev/null @@ -1,148 +0,0 @@ -body { - margin: 0; - padding: 0; - overflow: hidden; - background: var(--body-background); -} - -.header { - height: 100px; - width: 100%; - - background: var(--header-background); -} - -.header .arrow:hover { - color: transparent; - text-decoration: none; -} - -.header .resumes-control-title { - margin-left: 16px; - - font-family: Open Sans, serif; - font-style: normal; - font-weight: 600; - font-size: 20px; - - color: var(--header-text-color); -} - -.header .arrow-dot { - height: 30px; - width: 30px; - border-radius: 50%; - margin: 35px 0 0 25%; - background: var(--header-arrow-background); - display: inline-block; - text-align: center; -} - -.header .arrow-dot img { - width: 12px; - margin-top: 9px; - margin-left: -2px; -} - -.footer { - height: 100px; - width: 100%; - - position:absolute; - bottom:0; - - font-family: Open Sans, serif; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 19px; - - display: table; - - color: var(--footer-text-color); - background: var(--header-background); -} - -.footer a { - display:table-cell; - vertical-align:middle; -} - -.footer div { - width: 100%; - text-align: center; -} - -.scrollable-panel { - height: calc(100vh - 200px); - width: 100%; - margin: 0; - overflow: auto; -} - -.text-anchor { - text-decoration: none; -} - -.text-anchor:hover { - opacity: 0.8; - color: var(--anchor-color); - text-decoration: underline; -} - -.no-underline-anchor { - text-decoration: none; -} - -.no-underline-anchor:hover { - opacity: 0.8; -} - -.footer-text-anchor { - color: var(--footer-anchor-color); - text-decoration: none; -} - -.footer-text-anchor:hover { - opacity: 0.8; - text-decoration: underline; -} - -.themes { - font-family: Roboto, serif; - font-style: normal; - font-weight: bold; - font-size: 16px; - line-height: 19px; - - float: right; - display: flex; - margin: 40px 24px 0 0; - - color: var(--theme-text-color); -} - -.theme-title { - width: 45px; -} - -.theme-selector option { - color: var(--table-header-background); - background: var(--table-header-text-color); -} - -.theme-selector select { - color: var(--table-header-text-color); - background: var(--table-header-background); - border: none; -} - -.contact-link { - color: var(--contact-link-color); - text-decoration: none; -} - -.contact-link:hover { - text-decoration: underline; - opacity: 0.8; -} diff --git a/web/css/theme/dark.css b/web/css/theme/dark.css deleted file mode 100644 index 9c11d973..00000000 --- a/web/css/theme/dark.css +++ /dev/null @@ -1,27 +0,0 @@ -:root { - --header-background: #2A343D; - --header-text-color: #F8F9FA; - --header-arrow-background: #FFFFFF; - --footer-text-color: #F8F9FA; - --footer-anchor-color: #F8F9FA; - --anchor-color: #F8F9FA; - --text-color: #ECEEF2; - --add-resume-text-color: #3F9752; - --body-background: #1A2026; - --table-header-text-color: #F8F9FA; - --table-header-background: #0A0C0F; - --table-text-color: #F8F9FA; - --table-odd-row-background: #12161A; - --table-even-row-background: #1A2026; - --table-shadow-color: rgba(0, 0, 0, 0.5); - --input-field-background: #2A343D; - --input-field-shadow: rgba(0, 0, 0, 0.3); - --spacer-background: #E0E4EA; - --submit-button-color: #3F9752; - --submit-button-background: #1A2026; - --save-button-background: #3F9752; - --cancel-button-color: #F38064; - --button-text-color: #F8F9FA; - --theme-text-color: #ECEEF2; - --contact-link-color: #169FE1; -} \ No newline at end of file diff --git a/web/css/theme/light.css b/web/css/theme/light.css deleted file mode 100644 index 33660a3d..00000000 --- a/web/css/theme/light.css +++ /dev/null @@ -1,27 +0,0 @@ -:root { - --header-background: #EDEFF2; - --header-text-color: #4A586E; - --header-arrow-background: #FFFFFF; - --footer-text-color: #4A586E; - --footer-anchor-color: #4A586E; - --anchor-color: #4A586E; - --text-color: #4A586E; - --add-resume-text-color: #4A586E; - --body-background: #FFFFFF; - --table-header-text-color: #4A586E; - --table-header-background: #E0E4EA; - --table-text-color: #F8F9FA; - --table-odd-row-background: #ECEEF2; - --table-even-row-background: #F8F9FA; - --table-shadow-color: none; - --input-field-background: #F8F9FA; - --input-field-shadow: #E0E4EA; - --spacer-background: #E0E4EA; - --submit-button-color: #319848; - --submit-button-background: #FFFFFF; - --save-button-background: #319848; - --cancel-button-color: #B7616A; - --button-text-color: #F8F9FA; - --theme-text-color: #4A586E; - --contact-link-color: #169FE1; -} \ No newline at end of file diff --git a/web/css/theme/purple.css b/web/css/theme/purple.css deleted file mode 100644 index b3af212c..00000000 --- a/web/css/theme/purple.css +++ /dev/null @@ -1,27 +0,0 @@ -:root { - --header-background: #7339D4; - --header-text-color: #ECEEF2; - --header-arrow-background: #FFFFFF; - --footer-text-color: #F8F9FA; - --footer-anchor-color: #F8F9FA; - --anchor-color: #F8F9FA; - --text-color: #ECEEF2; - --add-resume-text-color: #F8F9FA; - --body-background: #6129BD; - --table-header-text-color: #F8F9FA; - --table-header-background: #5A10D3; - --table-text-color: #F8F9FA; - --table-odd-row-background: #6212E5; - --table-even-row-background: #6C1DEE; - --table-shadow-color: 0 0 50px rgba(67, 12, 156, 0.5); - --input-field-background: #8A59DB; - --input-field-shadow: #8A59DB; - --spacer-background: #E0E4EA; - --submit-button-color: #ECEEF2; - --submit-button-background: #6129BD; - --save-button-background: #319848; - --cancel-button-color: #AE515A; - --button-text-color: #F8F9FA; - --theme-text-color: #ECEEF2; - --contact-link-color: #169FE1; -} \ No newline at end of file diff --git a/web/css/view-resume-styles.css b/web/css/view-resume-styles.css deleted file mode 100644 index d82beeb1..00000000 --- a/web/css/view-resume-styles.css +++ /dev/null @@ -1,100 +0,0 @@ -.form-wrapper { - font-family: Open Sans, serif; - font-style: normal; - font-weight: 600; - color: var(--text-color); - - height: 100%; - min-width: 610px; - width: 50%; - margin: 0 0 0 25%; - display: block; -} - -.full-name { - font-size: 32px; - line-height: 44px; - margin-top: 40px; -} - -.contacts { - font-weight: 300; - font-size: 18px; - line-height: 30px; - margin-top: 21px; -} - -.section-wrapper { - margin-bottom: 83px; -} - -.spacer { - width: 100%; - min-width: calc(100% + 50px); - height: 2px; - margin: 43px 0 77px 0; - - background: var(--spacer-background); - border-radius: 10px; -} - -.section { - font-weight: 600; - font-size: 24px; - line-height: 33px; - margin: 40px 0 24px 0; -} - -.position { - font-weight: 600; - font-size: 18px; - line-height: 25px; -} - -.qualities { - font-weight: 300; - font-size: 18px; - line-height: 25px; -} - -.list { - font-weight: 300; - font-size: 18px; - line-height: 25px; -} - -.job-name { - font-weight: bold; - font-size: 22px; - line-height: 30px; - margin-left: 207px; -} - -.period-position { - display: flex; - margin-top: 10px; -} - -.period { - font-weight: 300; - font-size: 18px; - line-height: 25px; - min-width: 207px; -} - -.position { - font-weight: bold; - font-size: 18px; - line-height: 25px; -} - -.description { - font-weight: 300; - font-size: 18px; - line-height: 25px; - margin: 35px 0 0 207px; -} - -.footer-spacer { - height: 10px; -} \ No newline at end of file diff --git a/web/img/add.png b/web/img/add.png new file mode 100644 index 00000000..0ea124a7 Binary files /dev/null and b/web/img/add.png differ diff --git a/web/img/dark/add-person.svg b/web/img/dark/add-person.svg deleted file mode 100644 index 1f780704..00000000 --- a/web/img/dark/add-person.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/img/dark/edit.svg b/web/img/dark/edit.svg deleted file mode 100644 index 45f5d190..00000000 --- a/web/img/dark/edit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/img/dark/remove.svg b/web/img/dark/remove.svg deleted file mode 100644 index a504d5ca..00000000 --- a/web/img/dark/remove.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/img/delete.png b/web/img/delete.png new file mode 100644 index 00000000..ace289ed Binary files /dev/null and b/web/img/delete.png differ diff --git a/web/img/email.png b/web/img/email.png new file mode 100644 index 00000000..83278739 Binary files /dev/null and b/web/img/email.png differ diff --git a/web/img/gh.png b/web/img/gh.png new file mode 100644 index 00000000..f1c40a4a Binary files /dev/null and b/web/img/gh.png differ diff --git a/web/img/left_arrow.svg b/web/img/left_arrow.svg deleted file mode 100644 index c7325c1c..00000000 --- a/web/img/left_arrow.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/img/light/add-person.svg b/web/img/light/add-person.svg deleted file mode 100644 index fed04df9..00000000 --- a/web/img/light/add-person.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/web/img/light/edit.svg b/web/img/light/edit.svg deleted file mode 100644 index bcec11ae..00000000 --- a/web/img/light/edit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/img/light/remove.svg b/web/img/light/remove.svg deleted file mode 100644 index 0e96f987..00000000 --- a/web/img/light/remove.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/web/img/lin.png b/web/img/lin.png new file mode 100644 index 00000000..48678662 Binary files /dev/null and b/web/img/lin.png differ diff --git a/web/img/pencil.png b/web/img/pencil.png new file mode 100644 index 00000000..d5ba3d59 Binary files /dev/null and b/web/img/pencil.png differ diff --git a/web/img/purple/add-person.svg b/web/img/purple/add-person.svg deleted file mode 100644 index 8ee48c28..00000000 --- a/web/img/purple/add-person.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/img/purple/edit.svg b/web/img/purple/edit.svg deleted file mode 100644 index b6fe15cc..00000000 --- a/web/img/purple/edit.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/img/purple/remove.svg b/web/img/purple/remove.svg deleted file mode 100644 index d11f6c57..00000000 --- a/web/img/purple/remove.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/img/s.gif b/web/img/s.gif new file mode 100644 index 00000000..1d11fa9a Binary files /dev/null and b/web/img/s.gif differ diff --git a/web/img/skype.png b/web/img/skype.png new file mode 100644 index 00000000..7d5e24a6 Binary files /dev/null and b/web/img/skype.png differ diff --git a/web/img/so.png b/web/img/so.png new file mode 100644 index 00000000..dae5738a Binary files /dev/null and b/web/img/so.png differ diff --git a/web/test.html b/web/test.html index 9830809c..35fd7480 100644 --- a/web/test.html +++ b/web/test.html @@ -7,4 +7,4 @@ Test - \ No newline at end of file + \ No newline at end of file