package com.noticeditorteam.noticeditor.plugin.attachments;
import com.noticeditorteam.noticeditor.controller.NoticeController;
import com.noticeditorteam.noticeditor.io.IOUtil;
import com.noticeditorteam.noticeditor.model.Attachment;
import com.noticeditorteam.noticeditor.model.Attachments;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import javafx.concurrent.Task;
public final class FromURLImporter extends TextBasedImporter {
public FromURLImporter(ResourceBundle resources) {
super(resources);
System.setProperty("http.agent", "Mozilla/5.0 (Windows NT 6.1; WOW64)"
+ " AppleWebKit/537.36 (KHTML, like Gecko)"
+ " Chrome/51.0.2704.103 Safari/537.36");
}
@Override
public String name() {
return resources.getString("import_from_urls");
}
@Override
protected Task<Attachments> createTask() {
return new Task<Attachments>() {
@Override
protected Attachments call() throws Exception {
final String[] lines = getTextData().split("\n");
// Split urls into groups
final int numberOfGroups = Runtime.getRuntime().availableProcessors();
final int limitItems = (int) Math.ceil(lines.length / (double)numberOfGroups);
final List<List<String>> urlsGroup = splitUrlsIntoGroups(lines, limitItems);
// Actual number of groups
final int groupsSize = urlsGroup.size();
// Download in separate threads
final Logger logger = NoticeController.getLogger();
final Thread[] threads = new Thread[groupsSize];
final AtomicLong downloadsCount = new AtomicLong(0L);
final List<Attachment> attachments = new CopyOnWriteArrayList<>();
for (int i = 0; i < groupsSize; i++) {
final List<String> urls = urlsGroup.get(i);
threads[i] = new Thread(() -> {
final int urlsSize = urls.size();
for (String url : urls) {
if (isCancelled()) return;
try {
final Attachment att = new Attachment(
getFilenameFrom(url),
IOUtil.download(url));
attachments.add(att);
} catch (IOException ioe) {
logger.log(Level.SEVERE, url, ioe);
}
updateProgress(downloadsCount.incrementAndGet(), urlsSize);
}
});
threads[i].start();
}
// Wait until complete
for (Thread thread : threads) {
thread.join();
}
return new Attachments(attachments);
}
};
}
private List<List<String>> splitUrlsIntoGroups(String[] lines, int limitItems) {
return Stream.of(lines)
.filter(str -> str.startsWith("http"))
.collect(ArrayList::new,
(list, url) -> {
final boolean needNewList = (list.isEmpty() || (list.get(list.size() - 1).size() >= limitItems));
final List<String> innerList = needNewList
? new ArrayList<>(limitItems)
: list.get(list.size() - 1);
innerList.add(url);
if (needNewList) {
list.add(innerList);
}
},
(list1, list2) -> list1.addAll(list2));
}
private static String getFilenameFrom(final String url) {
String result = url;
final int lastSlash = url.lastIndexOf('/');
if (lastSlash > 0) {
result = url.substring(lastSlash + 1);
}
if (result.length() > 60) {
result = result.substring(result.length() - 60);
}
return result;
}
}