───────┬──────────────────────────────────────────────────────────────────────── │ File: src/main//java/jp/ac/kobe_u/cs/itspecialist/todoapp/service/ToDoService.java ───────┼──────────────────────────────────────────────────────────────────────── 1 │ package jp.ac.kobe_u.cs.itspecialist.todoapp.service; 2 │ 3 │ import java.util.Date; 4 │ import java.util.HashMap; 5 │ import java.util.List; 6 │ import java.util.Map; 7 │ import java.util.function.BiFunction; 8 │ import java.util.function.Function; 9 │ 10 │ import org.springframework.beans.factory.annotation.Autowired; 11 │ import org.springframework.data.util.Pair; 12 │ import org.springframework.stereotype.Service; 13 │ 14 │ import jp.ac.kobe_u.cs.itspecialist.todoapp.dto.ToDoForm; 15 │ import jp.ac.kobe_u.cs.itspecialist.todoapp.entity.ToDo; 16 │ import jp.ac.kobe_u.cs.itspecialist.todoapp.exception.ToDoAppException; 17 │ import jp.ac.kobe_u.cs.itspecialist.todoapp.repository.ToDoRepository; 18 │ 19 │ @Service 20 │ public class ToDoService { 21 │ @Autowired 22 │ MemberService mService; 23 │ @Autowired 24 │ ToDoRepository tRepo; 25 │ /** 26 │ * ToDoを作成する (C) 27 │ * @param mid 作成者 28 │ * @param form フォーム 29 │ * @return 30 │ */ 31 │ public ToDo createToDo(String mid, ToDoForm form) { 32 │ mService.getMember(mid); //実在メンバーか確認 33 │ ToDo todo = form.toEntity(); 34 │ todo.setMid(mid); 35 │ return tRepo.save(todo); 36 │ } 37 │ 38 │ /** 39 │ * ToDoを1つ取得する (R) 40 │ * @param seq 41 │ * @return 42 │ */ 43 │ public ToDo getToDo(Long seq) { 44 │ ToDo todo = tRepo.findById(seq).orElseThrow( 45 │ () -> new ToDoAppException(ToDoAppException.NO_SUCH_TODO_EXISTS, 46 │ seq + ": No such ToDo exists") 47 │ ); 48 │ return todo; 49 │ } 50 │ 51 │ /** 52 │ * あるメンバーのToDoリストを取得する (R) 53 │ * @param mid 54 │ * @return 55 │ */ 56 │ public List<ToDo> getToDoList(String mid, String sortBy, String order) { 57 │ BiFunction<String, Boolean, List<ToDo>> finder = midAndDoneFinder.getOrDefault(Pair.of(sortBy, order), 58 │ (memberId, doneFlag) -> tRepo.findByMidAndDone(memberId, doneFlag)); 59 │ return finder.apply(mid, false); 60 │ } 61 │ /** 62 │ * あるメンバーのDoneリストを取得する (R) 63 │ * @param mid 64 │ * @return 65 │ */ 66 │ public List<ToDo> getDoneList(String mid, String sortBy, String order) { 67 │ BiFunction<String, Boolean, List<ToDo>> finder = midAndDoneFinder.getOrDefault(Pair.of(sortBy, order), 68 │ (memberId, doneFlag) -> tRepo.findByMidAndDone(memberId, doneFlag)); 69 │ return finder.apply(mid, true); 70 │ } 71 │ 72 │ private final Map<Pair<String, String>, BiFunction<String, Boolean, List<ToDo>>> midAndDoneFinder = generateMidAndDoneFinder(); 73 │ private Map<Pair<String, String>, BiFunction<String, Boolean, List<ToDo>>> generateMidAndDoneFinder() { 74 │ Map<Pair<String, String>, BiFunction<String, Boolean, List<ToDo>>> map = new HashMap<>(); 75 │ map.put(Pair.of("seq", "asc"), (mid, done) -> tRepo.findByMidAndDoneOrderBySeqAsc(mid, done)); 76 │ map.put(Pair.of("seq", "desc"), (mid, done) -> tRepo.findByMidAndDoneOrderBySeqDesc(mid, done)); 77 │ map.put(Pair.of("title", "asc"), (mid, done) -> tRepo.findByMidAndDoneOrderByTitleAsc(mid, done)); 78 │ map.put(Pair.of("title", "desc"), (mid, done) -> tRepo.findByMidAndDoneOrderByTitleDesc(mid, done)); 79 │ map.put(Pair.of("created_at", "asc"), (mid, done) -> tRepo.findByMidAndDoneOrderByCreatedAtAsc(mid, done)); 80 │ map.put(Pair.of("created_at", "desc"), (mid, done) -> tRepo.findByMidAndDoneOrderByCreatedAtDesc(mid, done)); 81 │ map.put(Pair.of("done_at", "asc"), (mid, done) -> tRepo.findByMidAndDoneOrderByDoneAtAsc(mid, done)); 82 │ map.put(Pair.of("done_at", "desc"), (mid, done) -> tRepo.findByMidAndDoneOrderByDoneAtDesc(mid, done)); 83 │ return map; 84 │ } 85 │ 86 │ /** 87 │ * 全員のToDoリストを取得する (R) 88 │ * @return 89 │ */ 90 │ public List<ToDo> getToDoList(String sortBy, String order) { 91 │ Function<Boolean, List<ToDo>> finder = doneFinder.getOrDefault(Pair.of(sortBy, order), 92 │ (doneFlag) -> tRepo.findByDone(doneFlag)); 93 │ return finder.apply(false); 94 │ } 95 │ 96 │ /** 97 │ * 全員のDoneリストを取得する (R) 98 │ * @return 99 │ */ 100 │ public List<ToDo> getDoneList(String sortBy, String order) { 101 │ Function<Boolean, List<ToDo>> finder = doneFinder.getOrDefault(Pair.of(sortBy, order), 102 │ (doneFlag) -> tRepo.findByDone(doneFlag)); 103 │ return finder.apply(true); 104 │ } 105 │ 106 │ 107 │ private final Map<Pair<String, String>, Function<Boolean, List<ToDo>>> doneFinder = generateDoneFinder(); 108 │ private Map<Pair<String, String>, Function<Boolean, List<ToDo>>> generateDoneFinder() { 109 │ Map<Pair<String, String>, Function<Boolean, List<ToDo>>> map = new HashMap<>(); 110 │ map.put(Pair.of("seq", "asc"), (doneFlag) -> tRepo.findByDoneOrderBySeqAsc(doneFlag)); 111 │ map.put(Pair.of("seq", "desc"), (doneFlag) -> tRepo.findByDoneOrderBySeqDesc(doneFlag)); 112 │ map.put(Pair.of("title", "asc"), (doneFlag) -> tRepo.findByDoneOrderByTitleAsc(doneFlag)); 113 │ map.put(Pair.of("title", "desc"), (doneFlag) -> tRepo.findByDoneOrderByTitleDesc(doneFlag)); 114 │ map.put(Pair.of("mid", "asc"), (doneFlag) -> tRepo.findByDoneOrderByMidAsc(doneFlag)); 115 │ map.put(Pair.of("mid", "desc"), (doneFlag) -> tRepo.findByDoneOrderByMidDesc(doneFlag)); 116 │ map.put(Pair.of("created_at", "asc"), (doneFlag) -> tRepo.findByDoneOrderByCreatedAtAsc(doneFlag)); 117 │ map.put(Pair.of("created_at", "desc"), (doneFlag) -> tRepo.findByDoneOrderByCreatedAtDesc(doneFlag)); 118 │ map.put(Pair.of("done_at", "asc"), (doneFlag) -> tRepo.findByDoneOrderByDoneAtAsc(doneFlag)); 119 │ map.put(Pair.of("done_at", "desc"), (doneFlag) -> tRepo.findByDoneOrderByDoneAtDesc(doneFlag)); 120 │ return map; 121 │ } 122 │ 123 │ /** 124 │ * ToDoを完了する 125 │ * @param mid 完了者 126 │ * @param seq 完了するToDoの番号 127 │ * @return 128 │ */ 129 │ public ToDo done(String mid, Long seq) { 130 │ ToDo todo = getToDo(seq); 131 │ //Doneの認可を確認する.他人のToDoを閉めたらダメ. 132 │ if (!mid.equals(todo.getMid())) { 133 │ throw new ToDoAppException(ToDoAppException.INVALID_TODO_OPERATION, mid 134 │ + ": Cannot done other's todo of " + todo.getMid()); 135 │ } 136 │ todo.setDone(true); 137 │ todo.setDoneAt(new Date()); 138 │ return tRepo.save(todo); 139 │ } 140 │ 141 │ /** 142 │ * ToDoを更新する 143 │ * @param mid 更新者 144 │ * @param seq 更新するToDo番号 145 │ * @param form 更新フォーム 146 │ * @return 147 │ */ 148 │ public ToDo updateToDo(String mid, Long seq, ToDoForm form) { 149 │ ToDo todo = getToDo(seq); 150 │ //Doneの認可を確認する.他人のToDoを更新したらダメ. 151 │ if (!mid.equals(todo.getMid())) { 152 │ throw new ToDoAppException(ToDoAppException.INVALID_TODO_OPERATION, mid 153 │ + ": Cannot update other's todo of " + todo.getMid()); 154 │ } 155 │ todo.setTitle(form.getTitle()); //タイトルを更新 156 │ return tRepo.save(todo); 157 │ } 158 │ 159 │ /** 160 │ * ToDoを削除する 161 │ * @param mid 削除者 162 │ * @param seq 削除するToDo番号 163 │ */ 164 │ public void deleteToDo(String mid, Long seq) { 165 │ ToDo todo = getToDo(seq); 166 │ //Doneの認可を確認する.他人のToDoを削除したらダメ. 167 │ if (!mid.equals(todo.getMid())) { 168 │ throw new ToDoAppException(ToDoAppException.INVALID_TODO_OPERATION, mid 169 │ + ": Cannot delete other's todo of " + todo.getMid()); 170 │ } 171 │ tRepo.deleteById(seq); 172 │ } 173 │ 174 │ 175 │ 176 │ } ───────┴────────────────────────────────────────────────────────────────────────