OSDN Git Service

ダウンロード後変換処理に進む
[coroid/inqubus.git] / frontend / src / yukihane / inqubus / manager / TaskManage.java
1 package yukihane.inqubus.manager;
2
3 import java.io.File;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.concurrent.ExecutorService;
7 import java.util.concurrent.Executors;
8 import java.util.concurrent.Future;
9 import java.util.logging.Level;
10 import java.util.logging.Logger;
11 import saccubus.worker.WorkerListener;
12 import saccubus.worker.impl.MessageReportable;
13 import saccubus.worker.impl.PercentageReportable;
14 import saccubus.worker.impl.convert.Convert;
15 import saccubus.worker.impl.convert.ConvertProgress;
16 import saccubus.worker.impl.convert.ConvertResult;
17 import saccubus.worker.impl.download.Download;
18 import saccubus.worker.impl.download.DownloadProgress;
19 import saccubus.worker.impl.download.DownloadResult;
20 import saccubus.worker.profile.ConvertProfile;
21 import saccubus.worker.profile.DownloadProfile;
22
23 /**
24  *
25  * @author yuki
26  */
27 public class TaskManage {
28
29     private static final Logger logger = Logger.getLogger(TaskManage.class.getName());
30     private final ExecutorService downloadExecutorService;
31     private final ExecutorService convertExecutorService;
32     private final Map<Integer, ManageTarget<DownloadResult>> downloadTargets = new HashMap<>();
33     private final Map<Integer, ManageTarget<ConvertResult>> convertTargets = new HashMap<>();
34     private final TaskManageListener clientListener;
35
36     public TaskManage() {
37         this(1, 1, null);
38     }
39
40     public TaskManage(int maxDownload, int maxConvert) {
41         this(maxDownload, maxConvert, null);
42     }
43
44     public TaskManage(int maxDownload, int maxConvert, TaskManageListener listener) {
45         downloadExecutorService = Executors.newFixedThreadPool(maxDownload);
46         convertExecutorService = Executors.newFixedThreadPool(maxConvert);
47         this.clientListener = listener;
48     }
49
50     public synchronized boolean add(RequestProcess request) {
51         final DownloadProfile dp = request.getDownloadProfile();
52         final ConvertProfile cp = request.getConvertProfile();
53         if (dp != null && (dp.getVideoProfile().isDownload() || dp.getCommentProfile().isDownload())) {
54             // ダウンロードするものがあればまずダウンロード処理
55             final Download task = new Download(dp, request.getVideoId(),
56                     new DownloadListener(request.getRowId()));
57             final Future<DownloadResult> future = downloadExecutorService.submit(task);
58             downloadTargets.put(request.getRowId(), new ManageTarget<>(request, future));
59             return true;
60
61         } else if (cp != null && cp.isConvert()) {
62             final Convert task = new Convert(cp, dp.getVideoProfile().getLocalFile(), dp.getCommentProfile().
63                     getLocalFile(), new ConvertListener(request.getRowId()));
64             final Future<ConvertResult> future = convertExecutorService.submit(task);
65             convertTargets.put(request.getRowId(), new ManageTarget<>(request, future));
66             return true;
67         }
68         return false;
69     }
70
71     private class DownloadListener extends TaskManageInnerListener<DownloadResult, DownloadProgress> {
72
73         private DownloadListener(int rowId) {
74             super(rowId);
75         }
76
77         @Override
78         public void done(DownloadResult result) {
79             super.done(result);
80             synchronized (TaskManage.this) {
81                 final ManageTarget<DownloadResult> mt = downloadTargets.remove(Integer.valueOf(getRowId()));
82                 final RequestProcess request = mt.getRequest();
83                 if (request.getConvertProfile().isConvert()) {
84                     final DownloadProfile dp = request.getDownloadProfile();
85                     final File video = (dp.getVideoProfile().isDownload()) ? result.getDownloadVideo() : dp.
86                             getVideoProfile().getLocalFile();
87                     final File comment = (dp.getCommentProfile().isDownload()) ? result.getDownloadComment() : dp.
88                             getCommentProfile().getLocalFile();
89                     final ConvertProfile cp = request.getConvertProfile();
90                     final Convert task = new Convert(cp, video, comment, new ConvertListener(getRowId()));
91                     final Future<ConvertResult> future = convertExecutorService.submit(task);
92                     convertTargets.put(request.getRowId(), new ManageTarget<>(request, future));
93                 }
94                 // TODO 変換が必要なら変換キューに入れる
95             }
96
97         }
98
99         @Override
100         protected TaskKind getKind() {
101             return TaskKind.DOWNLOAD;
102         }
103     }
104
105     private class ConvertListener extends TaskManageInnerListener<ConvertResult, ConvertProgress> {
106
107         private ConvertListener(int rowId) {
108             super(rowId);
109         }
110
111         @Override
112         protected TaskKind getKind() {
113             return TaskKind.CONVERT;
114         }
115
116         @Override
117         public void done(ConvertResult result) {
118             super.done(result);
119             synchronized (TaskManage.this) {
120                 convertTargets.remove(getRowId());
121             }
122         }
123     }
124
125     abstract class TaskManageInnerListener<T, V extends PercentageReportable & MessageReportable> implements WorkerListener<T, V> {
126
127         private final int rowId;
128
129         protected TaskManageInnerListener(int rowId) {
130             this.rowId = rowId;
131         }
132
133         protected int getRowId() {
134             return rowId;
135         }
136
137         private void notify(TaskStatus status) {
138             notify(status, 0.0, "");
139         }
140
141         private void notify(TaskStatus status, double percentage, String message) {
142             if (getListener() == null) {
143                 return;
144             }
145             getListener().process(rowId, getKind(), status, percentage, message);
146         }
147
148         private TaskManageListener getListener() {
149             return clientListener;
150         }
151
152         protected abstract TaskKind getKind();
153
154         @Override
155         public void process(V progress) {
156             logger.log(Level.FINEST, "process: {0}", progress);
157             notify(TaskStatus.DOING, progress.getPercentage(), progress.getMessage());
158         }
159
160         @Override
161         public void cancelled() {
162             logger.log(Level.FINE, "cancelled: {0}", toString());
163             notify(TaskStatus.CANCELLED);
164         }
165
166         @Override
167         public void done(T result) {
168             logger.log(Level.FINE, "done: {0}", result);
169             notify(TaskStatus.DONE);
170         }
171
172         @Override
173         public void error(Throwable th) {
174             logger.log(Level.SEVERE, "error", th);
175             notify(TaskStatus.ERROR, 0.0, th.getMessage());
176         }
177     }
178
179     class ManageTarget<T> {
180
181         private final RequestProcess request;
182         private final Future<T> future;
183
184         ManageTarget(RequestProcess request, Future<T> future) {
185             this.request = request;
186             this.future = future;
187         }
188
189         Future<T> getFuture() {
190             return future;
191         }
192
193         RequestProcess getRequest() {
194             return request;
195         }
196     }
197 }