forked from JavaOPs/topjava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2_2_HW1_optional.patch
More file actions
398 lines (380 loc) · 14 KB
/
2_2_HW1_optional.patch
File metadata and controls
398 lines (380 loc) · 14 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
Index: src/main/webapp/mealForm.jsp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/webapp/mealForm.jsp (date 1530651650797)
+++ src/main/webapp/mealForm.jsp (date 1530651650797)
@@ -0,0 +1,51 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<html>
+<head>
+ <title>Meal</title>
+ <style>
+ 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;
+ }
+ </style>
+</head>
+<body>
+<section>
+ <h3><a href="index.html">Home</a></h3>
+ <h2>${param.action == 'create' ? 'Create meal' : 'Edit meal'}</h2>
+ <hr>
+ <jsp:useBean id="meal" type="ru.javawebinar.topjava.model.Meal" scope="request"/>
+ <form method="post" action="meals">
+ <input type="hidden" name="id" value="${meal.id}">
+ <dl>
+ <dt>DateTime:</dt>
+ <dd><input type="datetime-local" value="${meal.dateTime}" name="dateTime" required></dd>
+ </dl>
+ <dl>
+ <dt>Description:</dt>
+ <dd><input type="text" value="${meal.description}" size=40 name="description" required></dd>
+ </dl>
+ <dl>
+ <dt>Calories:</dt>
+ <dd><input type="number" value="${meal.calories}" name="calories" required></dd>
+ </dl>
+ <button type="submit">Save</button>
+ <button onclick="window.history.back()" type="button">Cancel</button>
+ </form>
+</section>
+</body>
+</html>
Index: src/main/java/ru/javawebinar/topjava/repository/MealRepository.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/repository/MealRepository.java (date 1530651607835)
+++ src/main/java/ru/javawebinar/topjava/repository/MealRepository.java (date 1530651607835)
@@ -0,0 +1,15 @@
+package ru.javawebinar.topjava.repository;
+
+import ru.javawebinar.topjava.model.Meal;
+
+import java.util.Collection;
+
+public interface MealRepository {
+ Meal save(Meal meal);
+
+ void delete(int id);
+
+ Meal get(int id);
+
+ Collection<Meal> getAll();
+}
Index: src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepositoryImpl.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepositoryImpl.java (date 1530651607825)
+++ src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepositoryImpl.java (date 1530651607825)
@@ -0,0 +1,45 @@
+package ru.javawebinar.topjava.repository;
+
+import ru.javawebinar.topjava.model.Meal;
+import ru.javawebinar.topjava.util.MealsUtil;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class InMemoryMealRepositoryImpl implements MealRepository {
+ private Map<Integer, Meal> repository = new ConcurrentHashMap<>();
+ private AtomicInteger counter = new AtomicInteger(0);
+
+ {
+ MealsUtil.MEALS.forEach(this::save);
+ }
+
+ @Override
+ public Meal save(Meal meal) {
+ if (meal.isNew()) {
+ meal.setId(counter.incrementAndGet());
+ repository.put(meal.getId(), meal);
+ return meal;
+ }
+ // treat case: update, but absent in storage
+ return repository.computeIfPresent(meal.getId(), (id, oldMeal) -> meal);
+ }
+
+ @Override
+ public void delete(int id) {
+ repository.remove(id);
+ }
+
+ @Override
+ public Meal get(int id) {
+ return repository.get(id);
+ }
+
+ @Override
+ public Collection<Meal> getAll() {
+ return repository.values();
+ }
+}
+
Index: src/main/java/ru/javawebinar/topjava/web/MealServlet.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/web/MealServlet.java (date 1530651578000)
+++ src/main/java/ru/javawebinar/topjava/web/MealServlet.java (date 1530651650782)
@@ -2,21 +2,78 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import ru.javawebinar.topjava.model.Meal;
+import ru.javawebinar.topjava.repository.InMemoryMealRepositoryImpl;
+import ru.javawebinar.topjava.repository.MealRepository;
import ru.javawebinar.topjava.util.MealsUtil;
+import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Objects;
public class MealServlet extends HttpServlet {
private static final Logger log = LoggerFactory.getLogger(MealServlet.class);
+ private MealRepository repository;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ repository = new InMemoryMealRepositoryImpl();
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ request.setCharacterEncoding("UTF-8");
+ String id = request.getParameter("id");
+
+ Meal meal = new Meal(id.isEmpty() ? null : Integer.valueOf(id),
+ LocalDateTime.parse(request.getParameter("dateTime")),
+ request.getParameter("description"),
+ Integer.parseInt(request.getParameter("calories")));
+
+ log.info(meal.isNew() ? "Create {}" : "Update {}", meal);
+ repository.save(meal);
+ response.sendRedirect("meals");
+ }
+
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- log.info("getAll");
- request.setAttribute("meals", MealsUtil.getWithExceeded(MealsUtil.MEALS, MealsUtil.DEFAULT_CALORIES_PER_DAY));
- request.getRequestDispatcher("/meals.jsp").forward(request, response);
+ String action = request.getParameter("action");
+
+ switch (action == null ? "all" : action) {
+ case "delete":
+ int id = getId(request);
+ log.info("Delete {}", id);
+ repository.delete(id);
+ response.sendRedirect("meals");
+ break;
+ case "create":
+ case "update":
+ final Meal meal = "create".equals(action) ?
+ new Meal(LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES), "", 1000) :
+ repository.get(getId(request));
+ request.setAttribute("meal", meal);
+ request.getRequestDispatcher("/mealForm.jsp").forward(request, response);
+ break;
+ case "all":
+ default:
+ log.info("getAll");
+ request.setAttribute("meals",
+ MealsUtil.getWithExceeded(repository.getAll(), MealsUtil.DEFAULT_CALORIES_PER_DAY));
+ request.getRequestDispatcher("/meals.jsp").forward(request, response);
+ break;
+ }
+ }
+
+ private int getId(HttpServletRequest request) {
+ String paramId = Objects.requireNonNull(request.getParameter("id"));
+ return Integer.parseInt(paramId);
}
}
Index: src/main/java/ru/javawebinar/topjava/model/MealWithExceed.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/model/MealWithExceed.java (date 1530651578000)
+++ src/main/java/ru/javawebinar/topjava/model/MealWithExceed.java (date 1530651607815)
@@ -3,6 +3,8 @@
import java.time.LocalDateTime;
public class MealWithExceed {
+ private final Integer id;
+
private final LocalDateTime dateTime;
private final String description;
@@ -11,13 +13,18 @@
private final boolean exceed;
- public MealWithExceed(LocalDateTime dateTime, String description, int calories, boolean exceed) {
+ public MealWithExceed(Integer id, LocalDateTime dateTime, String description, int calories, boolean exceed) {
+ this.id = id;
this.dateTime = dateTime;
this.description = description;
this.calories = calories;
this.exceed = exceed;
}
+ public Integer getId() {
+ return id;
+ }
+
public LocalDateTime getDateTime() {
return dateTime;
}
@@ -37,7 +44,8 @@
@Override
public String toString() {
return "MealWithExceed{" +
- "dateTime=" + dateTime +
+ "id=" + id +
+ ", dateTime=" + dateTime +
", description='" + description + '\'' +
", calories=" + calories +
", exceed=" + exceed +
Index: src/main/java/ru/javawebinar/topjava/model/Meal.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/model/Meal.java (date 1530651578000)
+++ src/main/java/ru/javawebinar/topjava/model/Meal.java (date 1530651607805)
@@ -5,6 +5,8 @@
import java.time.LocalTime;
public class Meal {
+ private Integer id;
+
private final LocalDateTime dateTime;
private final String description;
@@ -12,11 +14,24 @@
private final int calories;
public Meal(LocalDateTime dateTime, String description, int calories) {
+ this(null, dateTime, description, calories);
+ }
+
+ public Meal(Integer id, LocalDateTime dateTime, String description, int calories) {
+ this.id = id;
this.dateTime = dateTime;
this.description = description;
this.calories = calories;
}
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
public LocalDateTime getDateTime() {
return dateTime;
}
@@ -36,4 +51,18 @@
public LocalTime getTime() {
return dateTime.toLocalTime();
}
+
+ public boolean isNew() {
+ return id == null;
+ }
+
+ @Override
+ public String toString() {
+ return "Meal{" +
+ "id=" + id +
+ ", dateTime=" + dateTime +
+ ", description='" + description + '\'' +
+ ", calories=" + calories +
+ '}';
+ }
}
Index: src/main/java/ru/javawebinar/topjava/util/MealsUtil.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/util/MealsUtil.java (date 1530651578000)
+++ src/main/java/ru/javawebinar/topjava/util/MealsUtil.java (date 1530651650741)
@@ -25,15 +25,15 @@
public static final int DEFAULT_CALORIES_PER_DAY = 2000;
- public static List<MealWithExceed> getWithExceeded(List<Meal> meals, int caloriesPerDay) {
+ public static List<MealWithExceed> getWithExceeded(Collection<Meal> meals, int caloriesPerDay) {
return getFilteredWithExceeded(meals, caloriesPerDay, meal -> true);
}
- public static List<MealWithExceed> getFilteredWithExceeded(List<Meal> meals, int caloriesPerDay, LocalTime startTime, LocalTime endTime) {
+ public static List<MealWithExceed> getFilteredWithExceeded(Collection<Meal> meals, int caloriesPerDay, LocalTime startTime, LocalTime endTime) {
return getFilteredWithExceeded(meals, caloriesPerDay, meal -> DateTimeUtil.isBetween(meal.getTime(), startTime, endTime));
}
- private static List<MealWithExceed> getFilteredWithExceeded(List<Meal> meals, int caloriesPerDay, Predicate<Meal> filter) {
+ private static List<MealWithExceed> getFilteredWithExceeded(Collection<Meal> meals, int caloriesPerDay, Predicate<Meal> filter) {
Map<LocalDate, Integer> caloriesSumByDate = meals.stream()
.collect(
Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories))
@@ -47,6 +47,6 @@
}
public static MealWithExceed createWithExceed(Meal meal, boolean exceeded) {
- return new MealWithExceed(meal.getDateTime(), meal.getDescription(), meal.getCalories(), exceeded);
+ return new MealWithExceed(meal.getId(), meal.getDateTime(), meal.getDescription(), meal.getCalories(), exceeded);
}
}
\ No newline at end of file
Index: src/main/webapp/meals.jsp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/webapp/meals.jsp (date 1530651578000)
+++ src/main/webapp/meals.jsp (date 1530651650811)
@@ -20,6 +20,7 @@
<section>
<h3><a href="index.html">Home</a></h3>
<h2>Meals</h2>
+ <a href="meals?action=create">Add Meal</a>
<hr/>
<table border="1" cellpadding="8" cellspacing="0">
<thead>
@@ -27,6 +28,8 @@
<th>Date</th>
<th>Description</th>
<th>Calories</th>
+ <th></th>
+ <th></th>
</tr>
</thead>
<c:forEach items="${meals}" var="meal">
@@ -40,6 +43,8 @@
</td>
<td>${meal.description}</td>
<td>${meal.calories}</td>
+ <td><a href="meals?action=update&id=${meal.id}">Update</a></td>
+ <td><a href="meals?action=delete&id=${meal.id}">Delete</a></td>
</tr>
</c:forEach>
</table>