├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
└── vcs.xml
├── MyObject.txt
├── TaskTracker.iml
├── src
├── Main.java
├── subscribers
│ ├── BrowserLauncher.java
│ ├── FileLogger.java
│ ├── PopupNotifier.java
│ └── PopupNotifierWindow.java
└── tracker
│ ├── api
│ ├── IJournal.java
│ ├── IJournalSubscriber.java
│ ├── IManager.java
│ ├── ITask.java
│ ├── Period.java
│ └── PeriodOverlapException.java
│ └── impl
│ ├── Journal.java
│ ├── Manager.java
│ └── Task.java
└── temp
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | 1.8
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MyObject.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sunagatov/TaskTracker/5f652f1b8a34cf24c9781dcf511b745427839f8e/MyObject.txt
--------------------------------------------------------------------------------
/TaskTracker.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/Main.java:
--------------------------------------------------------------------------------
1 | import subscribers.PopupNotifier;
2 | import tracker.api.*;
3 | import tracker.impl.Manager;
4 |
5 | import java.io.IOException;
6 | import java.time.LocalDateTime;
7 | import java.time.format.DateTimeFormatter;
8 | import java.util.Scanner;
9 | import java.util.stream.Stream;
10 |
11 | public class Main {
12 | //20.12.2016 13:40:20
13 | public static void main(String[] args) {
14 | System.out.println("Welcome to the TaskTracker by Zufar! ");
15 | Scanner sc = new Scanner(System.in);
16 | IJournal journal = null;
17 | StringBuilder message1 = new StringBuilder("\nWhat do you want with journal? \n");
18 | message1.append(" - create \n");
19 | message1.append(" - load \n");
20 | String command;
21 | while (true) {
22 | System.out.print(message1);
23 | command = sc.nextLine();
24 | switch (command) {
25 | case "create": {
26 | journal = Manager.getInstance().createJournal();
27 | System.out.println("\nJournal created successfully.");
28 | break;
29 | }
30 | case "load": {
31 | try {
32 | journal = Manager.getInstance().loadJournal("C:\\Users\\ьр\\IdeaProjects\\TaskTracker");
33 | } catch (IOException | ClassNotFoundException e) {
34 | System.out.println("\nError! Journal can not be loaded.");
35 | continue;
36 | }
37 | break;
38 | }
39 | default: {
40 | System.out.println("\nThe wrong command! Try again...");
41 | continue;
42 | }
43 | }
44 | break;
45 | }
46 | journal.register(new PopupNotifier());
47 | StringBuilder message = new StringBuilder("\nWhat do you want with tasks? \n");
48 | message.append(" - add \n");
49 | message.append(" - delete \n");
50 | message.append(" - show \n");
51 | message.append(" - exit \n");
52 | message.append("Enter a command: ");
53 | while (true) {
54 | System.out.print(message);
55 | command = sc.nextLine();
56 | switch (command) {
57 | case "add": {
58 | System.out.print("\nEnter task name: ");
59 | String name = sc.nextLine();
60 | System.out.print("\nEnter task description: ");
61 | String description = sc.nextLine();
62 | while (true) {
63 | try {
64 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
65 | System.out.print("\nEnter start time. Format is DD.MM.YYYY HH:MM:SS: ");
66 | LocalDateTime startTime = LocalDateTime.parse(sc.nextLine(), formatter);
67 | if (LocalDateTime.now().isAfter(startTime)) {
68 | System.out.print("Error! StartTime must be after current time.");
69 | continue;
70 | }
71 | System.out.print("\nEnter End time. Format is DD.MM.YYYY HH:MM:SS: ");
72 | LocalDateTime endTime = LocalDateTime.parse(sc.nextLine(), formatter);
73 | if (endTime.isBefore(startTime)) {
74 | System.out.println("Error! EndTime must be after StarTime.");
75 | continue;
76 | }
77 | ITask task = journal.createTask(new Period(startTime, endTime));
78 | task.setDescription(description);
79 | task.setName(name);
80 | break;
81 | } catch (Exception e) {
82 | System.out.println("Error! Please type the time in the right way...\n");
83 | }
84 | }
85 |
86 | break;
87 | }
88 |
89 | case "delete": {
90 | System.out.print("Write a task name: ");
91 | String taskName = sc.nextLine().toLowerCase();
92 | Stream s = journal.getTasks(new Period(LocalDateTime.MIN, LocalDateTime.MAX)).stream().
93 | filter((task) -> task.getName().toLowerCase().contains(taskName));
94 | if (s.count() == 0 || journal.getNumberOfTasks() == 0) {
95 | System.out.println("Error! The task with that name is not existed!");
96 | continue;
97 | }
98 | journal.getTasks(new Period(LocalDateTime.MIN, LocalDateTime.MAX)).stream().
99 | filter((task) -> task.getName().toLowerCase().contains(taskName)).
100 | forEach(journal::removeTask);
101 | System.out.println("\nThe Task was removed successfully.");
102 | break;
103 | }
104 |
105 | case "show": {
106 | System.out.println("Number of Tasks: " + journal.getNumberOfTasks());
107 | System.out.println("================");
108 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
109 | final IJournal finalJournal = journal;
110 | journal.getTasks(new Period(LocalDateTime.MIN, LocalDateTime.MAX)).stream().
111 | forEach((task) -> {
112 | Period period = finalJournal.getTaskPeriod(task);
113 | System.out.println("ID: " + task.getId());
114 | System.out.println("Name: " + task.getName());
115 | System.out.println("Description: " + task.getDescription());
116 | System.out.println("StartTime: " + period.getStart().format(formatter));
117 | System.out.println("EndTime: " + period.getEnd().format(formatter));
118 | System.out.println("================");
119 | });
120 | break;
121 | }
122 |
123 | case "exit": {
124 | /* try {
125 | Manager.getInstance().saveJournal(journal, "MyObject.txt");
126 | } catch (IOException e) {
127 | e.printStackTrace();
128 | }*/
129 | //System.out.println("\nJournal was saved successfully.");
130 | return;
131 | }
132 |
133 | default:
134 | System.out.println("\nThe wrong command! Try again...");
135 | }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/subscribers/BrowserLauncher.java:
--------------------------------------------------------------------------------
1 | package subscribers;
2 |
3 | import tracker.api.IJournal;
4 | import tracker.api.IJournalSubscriber;
5 | import tracker.api.ITask;
6 |
7 | public class BrowserLauncher implements IJournalSubscriber {
8 | @Override
9 | public void onEvent(IJournal sender, ITask task) {
10 | // https://tasktracker.org/?journal={$id}&task={$id}
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/subscribers/FileLogger.java:
--------------------------------------------------------------------------------
1 | package subscribers;
2 |
3 | import tracker.api.IJournal;
4 | import tracker.api.IJournalSubscriber;
5 | import tracker.api.ITask;
6 |
7 | public class FileLogger implements IJournalSubscriber {
8 | @Override
9 | public void onEvent(IJournal sender, ITask task) {
10 | System.out.println(String.format("journal=%d, taskId=%d, taskName=%s, taskDesc=%s",
11 | sender.getId(), task.getId(), task.getName(), task.getDescription()));
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/subscribers/PopupNotifier.java:
--------------------------------------------------------------------------------
1 | package subscribers;
2 |
3 | import tracker.api.IJournal;
4 | import tracker.api.IJournalSubscriber;
5 | import tracker.api.ITask;
6 |
7 | import java.io.Serializable;
8 |
9 | public class PopupNotifier implements IJournalSubscriber {
10 | @Override
11 | public void onEvent(IJournal sender, ITask task) {
12 | PopupNotifierWindow w = new PopupNotifierWindow(sender, task);
13 | w.setVisible(true);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/subscribers/PopupNotifierWindow.java:
--------------------------------------------------------------------------------
1 | package subscribers;
2 |
3 | import tracker.api.IJournal;
4 | import tracker.api.ITask;
5 | import tracker.api.Period;
6 | import tracker.api.PeriodOverlapException;
7 |
8 | import javax.swing.*;
9 | import java.awt.*;
10 | import java.time.LocalDateTime;
11 | import java.time.temporal.ChronoUnit;
12 |
13 | class PopupNotifierWindow extends JFrame {
14 |
15 | PopupNotifierWindow(IJournal journal, ITask task) {
16 | setSize(400, 200);
17 | Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
18 | setLocation(dim.width / 2 - getSize().width / 2, dim.height / 2 - getSize().height / 2);
19 | setLayout(new FlowLayout());
20 | setTitle(task.getName());
21 | JLabel nameLabel = new JLabel();
22 | nameLabel.setText(task.getDescription());
23 | JButton closeButton = new JButton();
24 | closeButton.setText("Close");
25 | closeButton.addActionListener((actionEvent) -> dispose());
26 | JButton postponeButton = new JButton();
27 | postponeButton.setText("Postpone");
28 | postponeButton.addActionListener((actionEvent) -> {
29 | // Запросить новый период
30 | LocalDateTime start = LocalDateTime.now().plusSeconds(5);
31 | Period old = journal.getTaskPeriod(task);
32 | long seconds = ChronoUnit.SECONDS.between(old.getStart(), old.getEnd());
33 | LocalDateTime end = start.plusSeconds(seconds);
34 | try {
35 | journal.setTaskPeriod(task, new Period(start, end));
36 | } catch (PeriodOverlapException e) {
37 | // Неверный период, запросить снова
38 | }
39 | dispose();
40 | });
41 | add(nameLabel);
42 | add(closeButton);
43 | add(postponeButton);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/tracker/api/IJournal.java:
--------------------------------------------------------------------------------
1 | package tracker.api;
2 |
3 | import java.util.Collection;
4 |
5 | /**
6 | * Базовый интерфейс для всех журналов.
7 | */
8 | public interface IJournal {
9 | /**
10 | * Возвращает уникальный идентификатор журнала.
11 | *
12 | * @return Уникальный идентификатор журнала.
13 | */
14 | int getId();
15 |
16 | /**
17 | * Возвращает количество задач.
18 | *
19 | * @return Количество задач.
20 | */
21 | int getNumberOfTasks();
22 |
23 | /**
24 | * Возвращает коллекцию задач из указанного периода.
25 | *
26 | * @param period Период для поиска задач.
27 | * @return Коллекция задач из указанного периода.
28 | */
29 | Collection getTasks(Period period);
30 |
31 | /**
32 | * Создаёт новую задачу с указанным периодом в коллекции задач.
33 | *
34 | * @param period Период задачи.
35 | * @return Созданная задача.
36 | * @throws PeriodOverlapException Если период новой задачи пересекается с любым из периодов уже существующих задач.
37 | */
38 | ITask createTask(Period period) throws PeriodOverlapException;
39 |
40 | /**
41 | * Удаляет задачу из коллекции.
42 | *
43 | * @param task Удаляемая задача.
44 | */
45 | void removeTask(ITask task);
46 |
47 | /**
48 | * Возвращает период указанной задачи.
49 | *
50 | * @param task Задача, период которой нужно получить.
51 | * @return Период указанной задачи.
52 | */
53 | Period getTaskPeriod(ITask task);
54 |
55 | /**
56 | * Устанавливает новый период для задачи.
57 | *
58 | * @param task Задача, период которой нужно установить.
59 | * @param period Новое значение периода.
60 | * @throws PeriodOverlapException Если новый период задачи пересекается с любым из периодов других задач.
61 | */
62 | void setTaskPeriod(ITask task, Period period) throws PeriodOverlapException;
63 |
64 | /**
65 | * Регистрирует нового подписчика на событие наступления задачи.
66 | *
67 | * @param subscriber Новый подписчик.
68 | */
69 | void register(IJournalSubscriber subscriber);
70 |
71 | /**
72 | * Удаляет подписчика из события наступления задачи.
73 | *
74 | * @param subscriber Удаляемый подписчик.
75 | */
76 | void unregister(IJournalSubscriber subscriber);
77 | }
78 |
--------------------------------------------------------------------------------
/src/tracker/api/IJournalSubscriber.java:
--------------------------------------------------------------------------------
1 | package tracker.api;
2 |
3 | /**
4 | * Базовый интерфейс для всех подписчиков на событие наступления задачи в журнале.
5 | */
6 | public interface IJournalSubscriber {
7 | /**
8 | * Обрабатывает событие наступления задачи.
9 | *
10 | * @param sender Журнал, в котором произошло событие.
11 | * @param task Задача, время наступления которой подошло.
12 | */
13 | void onEvent(IJournal sender, ITask task);
14 | }
15 |
--------------------------------------------------------------------------------
/src/tracker/api/IManager.java:
--------------------------------------------------------------------------------
1 | package tracker.api;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * Базовый интерфейс для управления журналами.
7 | */
8 | public interface IManager {
9 | /**
10 | * Загружает журнал по его имени.
11 | *
12 | * @param path Имя журнала.
13 | * @return Загруженный журнал.
14 | * @throws IOException Если возникла ошибка при загрузке журнала с указанным именем.
15 | */
16 | IJournal loadJournal(String path) throws IOException, ClassNotFoundException;
17 |
18 | /**
19 | * Сохраняет журнал, используя указанное имя.
20 | *
21 | * @param journal Сохраняемый журнал.
22 | * @param path Имя сохраняемого журнала.
23 | * @throws IOException Если возникла ошибка при сохранении журнала с указанным именем.
24 | */
25 | void saveJournal(IJournal journal, String path) throws IOException;
26 |
27 |
28 | /**
29 | * Создает новый журнал.
30 | *
31 | * @return Новый журнал.
32 | */
33 | IJournal createJournal();
34 | }
35 |
--------------------------------------------------------------------------------
/src/tracker/api/ITask.java:
--------------------------------------------------------------------------------
1 | package tracker.api;
2 |
3 | /**
4 | * Базовый интерфейс задачи.
5 | */
6 | public interface ITask {
7 | /**
8 | * Возвращает идентификатор задачи (уникальный в пределах журнала).
9 | *
10 | * @return Идентификатор задачи (уникальный в пределах журнала).
11 | */
12 | int getId();
13 |
14 | /**
15 | * Возвращает название задачи.
16 | *
17 | * @return Название задачи.
18 | */
19 | String getName();
20 |
21 | /**
22 | * Возвращает описание задачи.
23 | *
24 | * @return Описание задачи.
25 | */
26 | String getDescription();
27 |
28 | /**
29 | * Устанавливает новое название задачи.
30 | *
31 | * @param name Новое название.
32 | */
33 | void setName(String name);
34 |
35 | /**
36 | * Устанавливает новое описание задачи.
37 | *
38 | * @param description Новое описание.
39 | */
40 | void setDescription(String description);
41 | }
42 |
--------------------------------------------------------------------------------
/src/tracker/api/Period.java:
--------------------------------------------------------------------------------
1 | package tracker.api;
2 |
3 | import java.io.Serializable;
4 | import java.time.LocalDateTime;
5 |
6 | /**
7 | * Описывает период времени.
8 | */
9 | public class Period {
10 | private final LocalDateTime start;
11 | private final LocalDateTime end;
12 |
13 | /**
14 | * Создаёт объект, описывающий фиксированный период времени.
15 | * @param start Начало периода.
16 | * @param end Конец периода.
17 | * @throws IllegalArgumentException Если конец периода предшествует началу.
18 | */
19 | public Period(LocalDateTime start, LocalDateTime end) {
20 | if (start.isAfter(end))
21 | throw new IllegalArgumentException();
22 | this.start = start;
23 | this.end = end;
24 | }
25 |
26 | /**
27 | * Возвращает начало периода.
28 | * @return Начало периода.
29 | */
30 | public LocalDateTime getStart() {
31 | return start;
32 | }
33 |
34 | /**
35 | * Возвращает конец периода.
36 | * @return Конец периода.
37 | */
38 | public LocalDateTime getEnd() {
39 | return end;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/tracker/api/PeriodOverlapException.java:
--------------------------------------------------------------------------------
1 | package tracker.api;
2 |
3 | import java.util.Collection;
4 |
5 | /**
6 | * Исключение, генерируемое в случае наличия задач с пересекающимися периодами.
7 | */
8 | public class PeriodOverlapException extends Exception {
9 | private Collection overlappedTasks;
10 |
11 | /**
12 | * Создаёт исключение со списком задач, периоды которых пересекаются с новым периодом.
13 | *
14 | * @param overlappedTasks Список задач, периоды которых пересекаются с новым периодом.
15 | */
16 | public PeriodOverlapException(Collection overlappedTasks) {
17 | this.overlappedTasks = overlappedTasks;
18 | }
19 |
20 | /**
21 | * Возвращает список задач, периоды которых пересекаются с новым периодом.
22 | *
23 | * @return Список задач, периоды которых пересекаются с новым периодом.
24 | */
25 | public Collection getOverlappedTasks() {
26 | return overlappedTasks;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/tracker/impl/Journal.java:
--------------------------------------------------------------------------------
1 | package tracker.impl;
2 |
3 | import tracker.api.*;
4 | import tracker.api.Period;
5 |
6 | import java.io.Serializable;
7 | import java.time.*;
8 | import java.util.*;
9 | import java.util.stream.Collectors;
10 |
11 | /**
12 | * Реализация интерфейса {@link IJournal}.
13 | */
14 | class Journal implements IJournal {
15 | private class TimerTask extends java.util.TimerTask {
16 | private ITask task;
17 |
18 | public TimerTask(ITask task) {
19 | this.task = task;
20 | }
21 |
22 | public ITask getTask() {
23 | return task;
24 | }
25 |
26 | @Override
27 | public void run() {
28 | synchronized (subscribers) {
29 | for (IJournalSubscriber subscriber : subscribers) {
30 | new Thread(() -> subscriber.onEvent(Journal.this, task)).run();
31 | }
32 | }
33 | Journal.this.reschedule();
34 | }
35 | }
36 |
37 | private final int id;
38 | private Map data = new HashMap<>();
39 |
40 | private List subscribers = new ArrayList<>();
41 |
42 | private Timer timer = new Timer();
43 | private TimerTask timerTask;
44 |
45 | /**
46 | * Создаёт журнал с указанным идентификатором.
47 | *
48 | * @param id Идентификатор журнала.
49 | */
50 | public Journal(int id) {
51 | this.id = id;
52 | }
53 |
54 | @Override
55 | public int getId() {
56 | return id;
57 | }
58 |
59 | @Override
60 | public int getNumberOfTasks() {
61 | return data.size();
62 | }
63 |
64 | @Override
65 | public synchronized Collection getTasks(Period period) {
66 | LocalDateTime start = period.getStart();
67 | LocalDateTime end = period.getEnd();
68 | return data.entrySet().stream().
69 | filter((entry) -> {
70 | LocalDateTime taskStart = entry.getValue().getStart();
71 | LocalDateTime taskEnd = entry.getValue().getEnd();
72 | return start.isBefore(taskStart) && taskStart.isBefore(end) ||
73 | start.isBefore(taskEnd) && taskEnd.isBefore(end);
74 | }).
75 | map((entry) -> entry.getKey()).
76 | collect(Collectors.toList());
77 | }
78 |
79 | @Override
80 | public synchronized ITask createTask(Period period) throws PeriodOverlapException {
81 | checkPeriod(null, period);
82 | ITask task = new Task(generateTaskId());
83 | data.put(task, period);
84 | rescheduleOnAdd(task);
85 | return task;
86 | }
87 |
88 | @Override
89 | public synchronized void removeTask(ITask task) {
90 | data.remove(task);
91 | rescheduleOnRemove(task);
92 | }
93 |
94 | @Override
95 | public synchronized Period getTaskPeriod(ITask task) {
96 | return data.get(task);
97 | }
98 |
99 | @Override
100 | public synchronized void setTaskPeriod(ITask task, Period period) throws PeriodOverlapException {
101 | checkPeriod(task, period);
102 | Period oldPeriod = data.get(task);
103 | data.put(task, period);
104 | rescheduleOnUpdate(task, oldPeriod);
105 | }
106 |
107 | @Override
108 | public synchronized void register(IJournalSubscriber subscriber) {
109 | subscribers.add(subscriber);
110 | }
111 |
112 | @Override
113 | public synchronized void unregister(IJournalSubscriber subscriber) {
114 | subscribers.remove(subscriber);
115 | }
116 |
117 | private void checkPeriod(ITask task, Period newPeriod) throws PeriodOverlapException {
118 | LocalDateTime newStart = newPeriod.getStart();
119 | LocalDateTime newEnd = newPeriod.getEnd();
120 | List overlaps = data.entrySet().stream().
121 | filter((entry) -> {
122 | if (entry.getKey() == task)
123 | return false;
124 | Period period = entry.getValue();
125 | LocalDateTime start = period.getStart();
126 | LocalDateTime end = period.getEnd();
127 | return start.isBefore(newStart) && newStart.isBefore(end) ||
128 | start.isBefore(newEnd) && newEnd.isBefore(end) ||
129 | newStart.isBefore(start) && end.isBefore(newEnd) || start.isEqual(newStart)||end.isEqual(newEnd);
130 | }).
131 | map((entry) -> entry.getKey()).
132 | collect(Collectors.toList());
133 | if (overlaps.size() > 0)
134 | throw new PeriodOverlapException(overlaps);
135 | }
136 |
137 | private int generateTaskId() {
138 | while (data.entrySet().stream().anyMatch((entry) -> entry.getKey().getId() == taskId))
139 | ++taskId;
140 | return taskId;
141 | }
142 |
143 | private int taskId = 0;
144 |
145 | private void rescheduleOnAdd(ITask addedTask) {
146 | // Оптимизировать (вызывать reschedule только при действительной необходимости
147 | reschedule();
148 | }
149 |
150 | private void rescheduleOnRemove(ITask removedTask) {
151 | // Оптимизировать (вызывать reschedule только при действительной необходимости
152 | reschedule();
153 | }
154 |
155 | private void rescheduleOnUpdate(ITask updatedTask, Period oldPeriod) {
156 | // Оптимизировать (вызывать reschedule только при действительной необходимости
157 | reschedule();
158 | }
159 |
160 | private synchronized void reschedule() {
161 | LocalDateTime now = LocalDateTime.now();
162 | if (timerTask != null) {
163 | timerTask.cancel();
164 | timer.purge();
165 | timerTask = null;
166 | }
167 | Optional> nextEntry = data.entrySet().stream().
168 | filter((entry) -> entry.getValue().getStart().isAfter(now)).
169 | min(Comparator.comparing((entry) -> entry.getValue().getStart()));
170 |
171 |
172 | nextEntry.ifPresent((entry) ->
173 | {
174 | long millis = java.time.Duration.between(LocalDateTime.now(), entry.getValue().getStart()).toMillis();
175 | if (millis < 0)
176 | millis = 0;
177 | timerTask = new TimerTask(entry.getKey());
178 | timer.schedule(timerTask, millis);
179 | });
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/src/tracker/impl/Manager.java:
--------------------------------------------------------------------------------
1 | package tracker.impl;
2 |
3 | import tracker.api.IJournal;
4 | import tracker.api.IManager;
5 |
6 | import java.io.*;
7 | import java.util.Random;
8 |
9 | /**
10 | * Реализация интерфейса {@link IManager}.
11 | * Шаблон проектирования "Одиночка".
12 | */
13 | public class Manager implements IManager {
14 | private static IManager intance = new Manager();
15 |
16 | /**
17 | * Возвращает единственный экземпляр {@link IManager}, осуществляющий управление журналами.
18 | *
19 | * @return Единственный экземпляр {@link IManager}, осуществляющий управление журналами.
20 | */
21 | public static IManager getInstance() {
22 | return intance;
23 | }
24 |
25 | private Manager() {
26 | }
27 |
28 | @Override
29 | public IJournal loadJournal(String path) throws IOException, ClassNotFoundException {
30 | ObjectInputStream oin;
31 | try (FileInputStream fis = new FileInputStream(path)) {
32 | oin = new ObjectInputStream(fis);
33 | return (IJournal) oin.readObject();
34 | }
35 | }
36 |
37 | @Override
38 | public void saveJournal(IJournal journal, String path) throws IOException {
39 | try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("MyObject.txt"))) {
40 | out.writeObject(journal);
41 | out.close();
42 | }
43 | //throw new UnsupportedOperationException();
44 | }
45 |
46 | @Override
47 | public IJournal createJournal() {
48 | Random r = new Random();
49 | return new Journal(getRandomNumberInRange(0, Integer.MAX_VALUE-1));
50 | }
51 |
52 | private static int getRandomNumberInRange(int min, int max) {
53 | if (min >= max) {
54 | throw new IllegalArgumentException("max must be greater than min");
55 | }
56 | Random r = new Random();
57 | return r.nextInt((max - min) + 1) + min;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/tracker/impl/Task.java:
--------------------------------------------------------------------------------
1 | package tracker.impl;
2 |
3 | import tracker.api.ITask;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * Реализация интерфейса {@link ITask}.
9 | */
10 | class Task implements ITask {
11 | private final int id;
12 | private String name;
13 | private String description;
14 |
15 | /**
16 | * Создаёт задачу с указанным идентификатором.
17 | *
18 | * @param id Идентификатор задачи.
19 | */
20 | public Task(int id) {
21 | this.id = id;
22 | }
23 |
24 | @Override
25 | public int getId() {
26 | return id;
27 | }
28 |
29 | @Override
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | @Override
35 | public String getDescription() {
36 | return description;
37 | }
38 |
39 | @Override
40 | public void setName(String name) {
41 | this.name = name;
42 | }
43 |
44 | @Override
45 | public void setDescription(String description) {
46 | this.description = description;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/temp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sunagatov/TaskTracker/5f652f1b8a34cf24c9781dcf511b745427839f8e/temp
--------------------------------------------------------------------------------