the omdbAPI query is now in its own thread

This commit is contained in:
Jannik 2018-03-08 17:59:28 +01:00
parent b6a1c38353
commit b5256ddaa8
6 changed files with 222 additions and 289 deletions

1
.gitignore vendored
View File

@ -48,4 +48,5 @@ Temporary Items
config.xml
.directory
target/
apiKeys.json

View File

@ -94,8 +94,8 @@ import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.OMDbAPIController;
import kellerkinder.HomeFlix.controller.UpdateController;
import kellerkinder.HomeFlix.controller.apiQuery;
import kellerkinder.HomeFlix.datatypes.SourceDataType;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
@ -240,6 +240,7 @@ public class MainWindowController {
private String streamUrl;
private String ratingSortType;
private String local;
private String omdbAPIKey;
// text strings
private String errorPlay;
@ -250,7 +251,8 @@ public class MainWindowController {
public double size;
private int last;
private int selected;
private int indexTable;
private int indexList;
private int next;
private ResourceBundle bundle;
@ -272,8 +274,9 @@ public class MainWindowController {
private Properties props = new Properties();
private Main main;
private MainWindowController mainWindowController;
private UpdateController updateController;
private apiQuery ApiQuery;
private OMDbAPIController omdbAPIController;
private DBController dbController;
/**
@ -282,8 +285,9 @@ public class MainWindowController {
*/
void setMain(Main main) {
this.main = main;
mainWindowController = this;
dbController = new DBController(this.main, this);
ApiQuery = new apiQuery(this, dbController, this.main);
omdbAPIController = new OMDbAPIController(this, dbController, this.main);
}
void init() {
@ -310,11 +314,11 @@ public class MainWindowController {
filmsTreeTable.setShowRoot(false);
// write content into cell
columnTitle.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty());
columnRating.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty());
columnStreamUrl.setCellValueFactory(cellData -> cellData.getValue().getValue().streamUrlProperty());
columnTitle.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty());
columnSeason.setCellValueFactory(cellData -> cellData.getValue().getValue().seasonProperty().asObject());
columnEpisode.setCellValueFactory(cellData -> cellData.getValue().getValue().episodeProperty().asObject());
columnRating.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty());
// add columns to treeTableViewfilm
filmsTreeTable.getColumns().add(columnStreamUrl);
@ -322,7 +326,7 @@ public class MainWindowController {
filmsTreeTable.getColumns().add(columnRating);
filmsTreeTable.getColumns().add(columnSeason);
filmsTreeTable.getColumns().add(columnEpisode);
filmsTreeTable.getColumns().get(0).setVisible(false); //hide columnStreamUrl (column with file URL, important for opening a file/stream)
filmsTreeTable.getColumns().get(0).setVisible(false); //hide columnStreamUrl (important)
// context menu for treeTableViewfilm
filmsTreeTable.setContextMenu(menu);
@ -421,7 +425,7 @@ public class MainWindowController {
@Override
public void handle(ActionEvent event) {
dbController.like(streamUrl);
dbController.refresh(streamUrl, selected);
dbController.refresh(streamUrl, indexList);
refreshTable();
}
});
@ -430,7 +434,7 @@ public class MainWindowController {
@Override
public void handle(ActionEvent event) {
dbController.dislike(streamUrl);
dbController.refresh(streamUrl, selected);
dbController.refresh(streamUrl, indexList);
refreshTable();
}
});
@ -488,18 +492,25 @@ public class MainWindowController {
filmsTreeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
@Override
public void changed(ObservableValue<?> observable, Object oldVal, Object newVal) {
// last = selected; //for auto-play
selected = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected item
last = selected - 1;
next = selected + 1;
title = columnTitle.getCellData(selected); // get name of selected item
streamUrl = columnStreamUrl.getCellData(selected); // get file path of selected item
indexTable = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected item
indexList = filmsList.indexOf(filmsTreeTable.getSelectionModel().getSelectedItem().getValue());
last = indexTable - 1;
next = indexTable + 1;
title = columnTitle.getCellData(indexTable); // get name of selected item
streamUrl = columnStreamUrl.getCellData(indexTable); // get file path of selected item
if (filmsList.get(selected).getCached() == true) {
System.out.println("index table: " + indexTable);
System.out.println("index list: " + indexList);
System.out.println(title);
if (filmsList.get(indexList).getCached()) {
LOGGER.info("loading from cache: " + title);
dbController.readCache(streamUrl);
} else {
ApiQuery.startQuery(title, streamUrl); // start api query
omdbAPIController = new OMDbAPIController(mainWindowController, dbController, main);
Thread omdbAPIThread = new Thread(omdbAPIController);
omdbAPIThread.setName("OMDbAPI");
omdbAPIThread.start();
}
}
});
@ -667,7 +678,7 @@ public class MainWindowController {
// refresh the selected child of the root node
private void refreshTable() {
filmRoot.getChildren().get(selected).setValue(filmsList.get(selected));
filmRoot.getChildren().get(indexTable).setValue(filmsList.get(indexList));
}
/**
@ -936,6 +947,15 @@ public class MainWindowController {
} catch (IOException e) {
LOGGER.error(errorSave, e);
}
// try loading the omdbAPI key
try {
File file = new File(getClass().getClassLoader().getResource("apiKeys.json").getFile());
JsonObject apiKeys = Json.parse(new FileReader(file)).asObject();
omdbAPIKey = apiKeys.getString("omdbAPIKey", "");
} catch (Exception e) {
LOGGER.error("Cloud not load the omdbAPI key. Please contact the developer!", e);
}
}
// if AutoUpdate, then check for updates
@ -976,6 +996,14 @@ public class MainWindowController {
return color;
}
public String getTitle() {
return title;
}
public String getStreamUrl() {
return streamUrl;
}
public void setSize(Double input) {
this.size = input;
}
@ -984,6 +1012,14 @@ public class MainWindowController {
return size;
}
public int getIndexTable() {
return indexTable;
}
public int getIndexList() {
return indexList;
}
public void setAutoUpdate(boolean input) {
this.autoUpdate = input;
}
@ -1008,6 +1044,10 @@ public class MainWindowController {
return local;
}
public String getOmdbAPIKey() {
return omdbAPIKey;
}
public ObservableList<FilmTabelDataType> getFilmsList() {
return filmsList;
}

View File

@ -215,6 +215,7 @@ public class DBController {
* @param index of the film in LocalFilms list
*/
public void refresh(String streamUrl, int index) {
// FIXME we need to refresh the entry in the table as well, else indexOf for indexList won't work
LOGGER.info("refresh ...");
try {
Statement stmt = connection.createStatement();
@ -446,6 +447,9 @@ public class DBController {
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);
}
// FIXME see fixme at refresh()
// refresh(streamUrl, mainWindowController.getIndexList());
}
/**
@ -475,36 +479,40 @@ public class DBController {
*/
void addCache( String streamUrl, String Title, String Year, String Rated, String Released, String Runtime, String Genre, String Director,
String Writer, String Actors, String Plot, String Language, String Country, String Awards, String Metascore, String imdbRating,
String Type, String imdbVotes, String imdbID, String Poster, String Response) throws SQLException{
PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
LOGGER.info("adding to cache: " + Title);
ps.setString(1,streamUrl);
ps.setString(2,Title);
ps.setString(3,Year);
ps.setString(4,Rated);
ps.setString(5,Released);
ps.setString(6,Runtime);
ps.setString(7,Genre);
ps.setString(8,Director);
ps.setString(9,Writer);
ps.setString(10,Actors);
ps.setString(11,Plot);
ps.setString(12,Language);
ps.setString(13,Country);
ps.setString(14,Awards);
ps.setString(15,Metascore);
ps.setString(16,imdbRating);
ps.setString(17,imdbVotes);
ps.setString(18,imdbID);
ps.setString(19,Type);
ps.setString(20,Poster);
ps.setString(21,Response);
ps.addBatch();
ps.executeBatch();
connection.commit();
ps.close();
LOGGER.info("done!");
String Type, String imdbVotes, String imdbID, String Poster, String Response) {
try {
PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
LOGGER.info("adding to cache: " + Title);
ps.setString(1,streamUrl);
ps.setString(2,Title);
ps.setString(3,Year);
ps.setString(4,Rated);
ps.setString(5,Released);
ps.setString(6,Runtime);
ps.setString(7,Genre);
ps.setString(8,Director);
ps.setString(9,Writer);
ps.setString(10,Actors);
ps.setString(11,Plot);
ps.setString(12,Language);
ps.setString(13,Country);
ps.setString(14,Awards);
ps.setString(15,Metascore);
ps.setString(16,imdbRating);
ps.setString(17,imdbVotes);
ps.setString(18,imdbID);
ps.setString(19,Type);
ps.setString(20,Poster);
ps.setString(21,Response);
ps.addBatch();
ps.executeBatch();
connection.commit();
ps.close();
LOGGER.info("done!");
} catch (Exception e) {
LOGGER.error(e);
}
}
/**
@ -567,7 +575,6 @@ public class DBController {
mainWindowController.getPosterImageView().setImage(new Image("resources/icons/close_black_2048x2048.png"));
LOGGER.error(e);
}
mainWindowController.getPosterImageView().setImage(im);
} catch (SQLException e) {
LOGGER.error("Ups! an error occured!", e);

View File

@ -0,0 +1,124 @@
package kellerkinder.HomeFlix.controller;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import javafx.application.Platform;
import kellerkinder.HomeFlix.application.Main;
import kellerkinder.HomeFlix.application.MainWindowController;
public class OMDbAPIController implements Runnable {
private MainWindowController mainWindowController;
private DBController dbController;
private Main main;
private String[] responseString = new String[20];
private String URL = "https://www.omdbapi.com/?apikey=";
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
public OMDbAPIController(MainWindowController mainWindowController, DBController dbController, Main main){
this.mainWindowController = mainWindowController;
this.dbController = dbController;
this.main = main;
}
@Override
public void run() {
String output = null;
String posterPath = null;
// get by title, TODO implement search
try {
URL apiUrl = new URL(URL + mainWindowController.getOmdbAPIKey() + "&t="
+ mainWindowController.getTitle().replace(" ", "%20"));
BufferedReader ina = new BufferedReader(new InputStreamReader(apiUrl.openStream()));
output = ina.readLine();
ina.close();
LOGGER.info("response from " + URL + " was valid");
LOGGER.info(output);
} catch (IOException e) {
LOGGER.error("error while making api request or reading response");
LOGGER.error("response from " + URL + " was: \n" + output, e);
return;
}
JsonObject object = Json.parse(output).asObject();
responseString[0] = object.getString("Title", "");
responseString[1] = object.getString("Year", "");
responseString[2] = object.getString("Rated", "");
responseString[3] = object.getString("Released", "");
responseString[4] = object.getString("Runtime", "");
responseString[5] = object.getString("Genre", "");
responseString[6] = object.getString("Director", "");
responseString[7] = object.getString("Writer", "");
responseString[8] = object.getString("Actors", "");
responseString[9] = object.getString("Plot", "");
responseString[10] = object.getString("Language", "");
responseString[11] = object.getString("Country", "");
responseString[12] = object.getString("Awards", "");
responseString[13] = object.getString("Metascore", "");
responseString[14] = object.getString("imdbRating", "");
responseString[15] = object.getString("Type", "");
responseString[16] = object.getString("imdbVotes", "");
responseString[17] = object.getString("imdbID", "");
responseString[18] = object.getString("Poster", "");
responseString[19] = object.getString("Response", "");
//resize the image to fit in the posterImageView and add it to the cache
try {
BufferedImage originalImage = ImageIO.read(new URL(responseString[18])); //change path to where file is located
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImagePNG = resizeImage(originalImage, type, 198, 297);
posterPath = main.getPosterCache() + "/" + mainWindowController.getTitle() + ".png";
ImageIO.write(resizeImagePNG, "png", new File(posterPath));
LOGGER.info("adding poster to cache: "+posterPath);
} catch (Exception e) {
LOGGER.error(e);
}
// adding strings to the cache
dbController.addCache(mainWindowController.getStreamUrl(), responseString[0], responseString[1],
responseString[2], responseString[3], responseString[4], responseString[5], responseString[6],
responseString[7], responseString[8], responseString[9], responseString[10], responseString[11],
responseString[12], responseString[13], responseString[14], responseString[15], responseString[16],
responseString[17], posterPath, responseString[19]);
dbController.setCached(mainWindowController.getStreamUrl());
// load data to the MainWindowController
Platform.runLater(() -> {
dbController.readCache(mainWindowController.getStreamUrl());
});
}
/**
* resize a image
* @param originalImage is the original image
* @param type of the original image
* @param IMG_WIDTH width to resize
* @param IMG_HEIGHT heigth to resize
* @return resized image
*/
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
}

View File

@ -1,239 +0,0 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2018 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package kellerkinder.HomeFlix.controller;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Scanner;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import javafx.scene.image.Image;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import kellerkinder.HomeFlix.application.Main;
import kellerkinder.HomeFlix.application.MainWindowController;
public class apiQuery{
public apiQuery(MainWindowController m, DBController db, Main main){
mainWindowController=m;
dbController=db;
this.main = main;
}
private MainWindowController mainWindowController;
private DBController dbController;
private Main main;
private Image im;
private String[] responseString = new String[20];
private String posterCache;
private String apiURL = "https://www.omdbapi.com/?apikey=";
private String apiKey = "";
ArrayList<Text> responseText = new ArrayList<Text>();
ArrayList<Text> nameText = new ArrayList<Text>();
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
/**
* apiQuery for Project HomeFlix, sends a query to the omdb api
*/
public void startQuery(String title, String streamUrl){
URL queryURL = null;
Scanner sc = null;
String moviename = null;
String retdata = null;
String posterPath = null;
InputStream is = null;
BufferedReader br = null;
String fontFamily = main.getFONT_FAMILY();
posterCache = main.getPosterCache().toString();
int fontSize = (int) Math.round(mainWindowController.size);
responseText.removeAll(responseText);
nameText.removeAll(nameText);
try {
//get film title
sc = new Scanner(System.in);
moviename = title;
// in case of no or "" Film title
if (moviename == null || moviename.equals("")) {
LOGGER.warn("No movie found");
}
//remove unwanted blank
moviename = moviename.trim();
//replace blank with +
moviename = moviename.replace(" ", "+");
//queryURL is apiURL and additional parameters, response-types: http,json,xml (must be json, since the response is processed with minimal-json )
queryURL = new URL(apiURL + apiKey + "&t=" + moviename + "&plot=full&r=json");
is = queryURL.openStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
//read data from response Stream
while ((retdata = br.readLine()) != null) {
//cut the json response into separate strings
LOGGER.info(retdata);
JsonObject object = Json.parse(retdata).asObject();
responseString[0] = object.getString("Title", "");
responseString[1] = object.getString("Year", "");
responseString[2] = object.getString("Rated", "");
responseString[3] = object.getString("Released", "");
responseString[4] = object.getString("Runtime", "");
responseString[5] = object.getString("Genre", "");
responseString[6] = object.getString("Director", "");
responseString[7] = object.getString("Writer", "");
responseString[8] = object.getString("Actors", "");
responseString[9] = object.getString("Plot", "");
responseString[10] = object.getString("Language", "");
responseString[11] = object.getString("Country", "");
responseString[12] = object.getString("Awards", "");
responseString[13] = object.getString("Metascore", "");
responseString[14] = object.getString("imdbRating", "");
responseString[15] = object.getString("Type", "");
responseString[16] = object.getString("imdbVotes", "");
responseString[17] = object.getString("imdbID", "");
responseString[18] = object.getString("Poster", "");
responseString[19] = object.getString("Response", "");
//adding poster to cache
BufferedImage originalImage = ImageIO.read(new URL(responseString[18]));//change path to where file is located
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImagePNG = resizeImage(originalImage, type, 198, 297);
if (System.getProperty("os.name").equals("Linux")) {
posterPath = posterCache+"/"+title+".png";
ImageIO.write(resizeImagePNG, "png", new File(posterCache+"/"+title+".png")); //change path where you want it saved
} else {
ImageIO.write(resizeImagePNG, "png", new File(posterCache+"\\"+title+".png")); //change path where you want it saved
posterPath = posterCache+"\\"+title+".png";
}
LOGGER.info("adding poster to cache: "+posterPath);
//adding strings to the cache
dbController.addCache( streamUrl, responseString[0], responseString[1],responseString[2], responseString[3], responseString[4], responseString[5],
responseString[6], responseString[7], responseString[8], responseString[9], responseString[10],responseString[11], responseString[12],
responseString[13], responseString[14], responseString[15], responseString[16], responseString[17], posterPath,
responseString[19]);
dbController.setCached(streamUrl);
for (int i = 0; i < 20; i++) {
Text text = new Text(responseString[i] + "\n");
responseText.add(text);
responseText.get(i).setFont(Font.font(fontFamily, fontSize));
}
// if response == false then show mainWindowController.noFilmFound else create new Texts and add them to flowText
if (retdata.contains("\"Response\":\"False\"")) { // TODO + FIXME
mainWindowController.getTextFlow().getChildren().add(new Text(mainWindowController.getBundle().getString("noFilmFound")));
im = new Image("resources/icons/close_black_2048x2048.png");
mainWindowController.getPosterImageView().setImage(im);
} else {
nameText.add(0, new Text(mainWindowController.getBundle().getString("title") + ": "));
nameText.add(1, new Text(mainWindowController.getBundle().getString("year") + ": "));
nameText.add(2, new Text(mainWindowController.getBundle().getString("rating") + ": "));
nameText.add(3, new Text(mainWindowController.getBundle().getString("publishedOn") + ": "));
nameText.add(4, new Text(mainWindowController.getBundle().getString("duration") + ": "));
nameText.add(5, new Text(mainWindowController.getBundle().getString("genre") + ": "));
nameText.add(6, new Text(mainWindowController.getBundle().getString("director") + ": "));
nameText.add(7, new Text(mainWindowController.getBundle().getString("writer") + ": "));
nameText.add(8, new Text(mainWindowController.getBundle().getString("actors") + ": "));
nameText.add(9, new Text(mainWindowController.getBundle().getString("plot") + ": "));
nameText.add(10, new Text(mainWindowController.getBundle().getString("language") + ": "));
nameText.add(11, new Text(mainWindowController.getBundle().getString("country") + ": "));
nameText.add(12, new Text(mainWindowController.getBundle().getString("awards") + ": "));
nameText.add(13, new Text(mainWindowController.getBundle().getString("metascore") + ": "));
nameText.add(14, new Text(mainWindowController.getBundle().getString("imdbRating") + ": "));
nameText.add(15, new Text(mainWindowController.getBundle().getString("type") + ": "));
for (int i = 0; i < nameText.size(); i++) {
nameText.get(i).setFont(Font.font(fontFamily, FontWeight.BOLD, fontSize));
}
mainWindowController.getTextFlow().getChildren().remove(0,
mainWindowController.getTextFlow().getChildren().size());
for (int i = 0; i < nameText.size(); i++) {
mainWindowController.getTextFlow().getChildren().addAll(nameText.get(i), responseText.get(i));
}
// if there is no poster
if (responseString[18].equals("N/A")) {
im = new Image("resources/icons/close_black_2048x2048.png");
} else {
im = new Image(responseString[18]);
}
mainWindowController.getPosterImageView().setImage(im);
}
}
} catch (Exception e) {
mainWindowController.getTextFlow().getChildren().remove(0, mainWindowController.getTextFlow().getChildren().size());
mainWindowController.getTextFlow().getChildren().add(new Text(e.toString()));
LOGGER.error(e);
} finally {
//closes datainputStream, InputStream,Scanner if not already done
try {
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
if (sc != null) {
sc.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
}

View File

@ -42,7 +42,7 @@
<font>
<Font name="Arial" size="12.0" />
</font></JFXTextField>
<ImageView fx:id="image1" fitHeight="297.0" fitWidth="198.0" layoutX="481.0" layoutY="46.0" pickOnBounds="true" preserveRatio="true" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="44.0">
<ImageView fx:id="posterImageView" fitHeight="297.0" fitWidth="198.0" layoutX="481.0" layoutY="46.0" pickOnBounds="true" preserveRatio="true" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="44.0">
<image>
<Image url="@../icons/Homeflix_Poster.png" />
</image></ImageView>