package fetcher.model;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import fetcher.controller.MainController;
import javafx.application.Platform;
import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
*
* File name : PageEntry.java
*
* This class represents the abstraction for a single URL entry.
* Using Jsoup it fetches all the needed informations from the web page.
*
*/
public class PageEntry{
String URL;
String Name;
String Description;
Date DateAdded;
String pageSnapshot;
MainController controller;
HashSet<String> tags;
public PageEntry(String URLstr,MainController controller){
this.URL = URLstr;
this.controller = controller;
this.pageSnapshot = "images/octopus.png";
this.Description = "";
this.tags = new HashSet<String>();
//This is to 'reset' the filter by tags (Show all entries) .
tags.add("all");
Thread workerThread = new Thread(new Worker(true));
workerThread.start();
}
/**
* Constructor used just when loading from the json file.
* @param controller the mainController.
*/
public PageEntry(MainController controller){
this.controller = controller;
this.tags = new HashSet<String>();
tags.add("all");
Thread workerThread = new Thread(new Worker(false));
workerThread.start();
}
/**
* Loads the page provided by the URL parameter and uses Jsoup to retrieve its content.
* @return true if the page loading has success
*/
private boolean loadPage(){
Document doc;
try {
doc = Jsoup.connect(URL).userAgent("Mozilla").get();
} catch (HttpStatusException e){
System.out.println("Failed to load page : " + URL + " , HTTP status code received was : " + e.getStatusCode());
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
this.Name = doc.title();
this.DateAdded = Calendar.getInstance().getTime();
//Getting description
if(doc.select("p").first() != null)
Description = doc.select("p").first().text();
//Getting the pad absolute path.
final String padFolder = (new File(controller.pad.getpadName())).getParent();
Platform.runLater(new Runnable() {
@Override
public void run() {
String URL = getURL();
String dir = padFolder + File.separator + Utils.IMAGES_SUBFOLDER + File.separator;
if(!URL.contains("youtube")) {
pageSnapshot = "file:///" + dir + (new Snapshotter(getURL(), padFolder, controller)).getWebsiteSnapshot();
}
else{
pageSnapshot = "file:///" + dir + Snapshotter.getYoutubeThumbnail(getURL(),dir);
}
}
});
return true;
}
/**
* Creates a JsonObject containing a json representation of this PageEntry.
* @return savedJson is the JsonObject containing the fields of this PageEntry.
*/
public JsonObject saveEntry(){
JsonObject savedJson = new JsonObject();
JsonArray savedTags = new JsonArray();
savedJson.addProperty("URL",URL);
savedJson.addProperty("Name",Name);
savedJson.addProperty("Description",Description);
savedJson.addProperty("DateAdded", new SimpleDateFormat("dd MMMM yy , hh:mm:ss" , Locale.getDefault()).format(this.DateAdded));
savedJson.addProperty("pageSnapshot",pageSnapshot);
for(String tag : tags)
savedTags.add(new JsonPrimitive(tag));
savedJson.add("Tags", savedTags);
return savedJson;
}
/**
* Loads an entry based on a json Object.
* @param JsonObjectEntry the json object containing the entry.
* @throws ParseException
*/
public void loadEntry(JsonObject JsonObjectEntry) throws ParseException {
setURL(JsonObjectEntry.get("URL").getAsString());
setDescription(JsonObjectEntry.get("Description").getAsString());
setName(JsonObjectEntry.get("Name").getAsString());
setPageSnapshot(JsonObjectEntry.get("pageSnapshot").getAsString());
setDateAdded(new SimpleDateFormat("dd MMMM yy , hh:mm:ss", Locale.getDefault()).parse(JsonObjectEntry.get("DateAdded").getAsString()));
}
public String getURL() {
return URL;
}
public void setURL(String URL) {
this.URL = URL;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public Date getDateAdded() {
return DateAdded;
}
public void setDateAdded(Date dateAdded) {
DateAdded = dateAdded;
}
public String getPageSnapshot() {
return pageSnapshot;
}
public void setPageSnapshot(String pageSnapshot) {
this.pageSnapshot = pageSnapshot;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public void addTag(String tag){
this.tags.add(tag);
}
public HashSet<String> getTags() {
return tags;
}
public void setTags(HashSet<String> tags) {
this.tags = tags;
}
public void clearTags() {
tags.clear();
tags.add("all");
}
public void deleteTag(String selectedItem) {
if(tags.contains(selectedItem) && !selectedItem.equalsIgnoreCase("all")) tags.remove(selectedItem);
}
/**
* Worker class is used to load a single PageEntry from a Thread so that the main program doesn't get stuck.
*/
class Worker implements Runnable{
//The worker Thread is used both when loading a URL from the clipboard and when we are loading from json. This boolean makes the double-usage possible.
boolean loadFromURL;
public Worker(boolean loadFromUrl){
this.loadFromURL = loadFromUrl;
}
@Override
public void run() {
//If we are loading from a url we try to load the page. We return if the loading fails (so the controller won't be notified).
if(loadFromURL)
if(!loadPage()) return;
controller.notifyControllerNewEntry(PageEntry.this);
}
}
}