Implémentation de la classe de gestion des API + implémentation du NewsListModel
This commit is contained in:
parent
24fb79745d
commit
bc62a3b65c
|
@ -11,25 +11,52 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import Interfaces.Callback;
|
import Interfaces.Callback;
|
||||||
|
import Interfaces.DelayedCallback;
|
||||||
|
import Interfaces.Event;
|
||||||
|
import Interfaces.EventObserver;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
public class ApiCall implements Runnable {
|
public class ApiCall implements Runnable, EventObserver {
|
||||||
|
|
||||||
|
//Methode appelée une fois que la requete s'est terminé
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
|
//connection HTTP
|
||||||
private HttpURLConnection connection;
|
private HttpURLConnection connection;
|
||||||
|
//méthode HTTP
|
||||||
private String method;
|
private String method;
|
||||||
|
//est ce que cet appel d'API attend un évenement pour se lancer
|
||||||
|
private Boolean isDelayed = false;
|
||||||
|
//Methode appellée une fois l'évenement arrivé, il retourne la nouvelle URL et les nouveaux parametres POST
|
||||||
|
private DelayedCallback delayedCallback;
|
||||||
|
//ID et Type de l'évenement attendu
|
||||||
|
private String eventID;
|
||||||
|
private String eventType;
|
||||||
|
//objet contenant le thread de l'appel
|
||||||
|
private Thread thread;
|
||||||
|
//si une erreur surviens durant le delayedCallback, la boucle run doit tout arreter, cette variable sert a notifier run() de ça
|
||||||
|
private Boolean shouldStop = false;
|
||||||
|
|
||||||
|
|
||||||
public ApiCall(String URL, String method, Callback call) {
|
public ApiCall(String URL, String method, Callback call) {
|
||||||
this.callback = call;
|
this.callback = call;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
try {
|
try {
|
||||||
|
//création de la connection
|
||||||
URL url = new URL(URL);
|
URL url = new URL(URL);
|
||||||
this.connection = (HttpURLConnection) url.openConnection();
|
this.connection = (HttpURLConnection) url.openConnection();
|
||||||
this.connection.setRequestMethod(method);
|
this.connection.setRequestMethod(method);
|
||||||
this.connection.setDoInput(true);
|
//si on fait une requete GET, il faut interdire l'envoie de donnée POST
|
||||||
|
if(method == "GET") {
|
||||||
|
this.connection.setDoOutput(false);
|
||||||
|
}else {
|
||||||
this.connection.setDoOutput(true);
|
this.connection.setDoOutput(true);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("Impossible d'ouvrir l'URL: "+URL);
|
this.callback.onError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,19 +65,39 @@ public class ApiCall implements Runnable {
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Map.Entry pair = (Map.Entry)it.next();
|
Map.Entry pair = (Map.Entry)it.next();
|
||||||
this.connection.setRequestProperty((String)pair.getKey(), (String)pair.getValue());
|
this.connection.setRequestProperty((String)pair.getKey(), (String)pair.getValue());
|
||||||
it.remove(); // avoids a ConcurrentModificationException
|
it.remove(); // évite les erreurs en cas de modification concurente
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
//si notre appel est delayed, on endort le thread
|
||||||
|
if(this.isDelayed) {
|
||||||
try {
|
try {
|
||||||
//Send request
|
//on doit se synchroniser avec le thread avant de l'endormir
|
||||||
|
synchronized(this.thread) {
|
||||||
|
this.thread.wait();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
this.callback.onError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//si il y a eu une erreur durant le delayedallback, on stope le thread
|
||||||
|
if(this.shouldStop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
//On envoie les paramètres POST si besoin
|
||||||
|
if(this.method != "GET") {
|
||||||
DataOutputStream wr = new DataOutputStream (connection.getOutputStream ());
|
DataOutputStream wr = new DataOutputStream (connection.getOutputStream ());
|
||||||
|
//TODO: implémenter la gestion des parametres POST
|
||||||
wr.flush ();
|
wr.flush ();
|
||||||
wr.close ();
|
wr.close ();
|
||||||
|
}
|
||||||
|
|
||||||
//Get Response
|
//on récupère la réponse de la requete
|
||||||
InputStream is = connection.getInputStream();
|
InputStream is = connection.getInputStream();
|
||||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
|
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
|
||||||
String line;
|
String line;
|
||||||
|
@ -60,16 +107,69 @@ public class ApiCall implements Runnable {
|
||||||
}
|
}
|
||||||
rd.close();
|
rd.close();
|
||||||
|
|
||||||
this.callback.call(response.toString());
|
//transformation en objet JSON
|
||||||
|
try {
|
||||||
|
//raplce null values by empty strings
|
||||||
|
JSONObject json = new JSONObject(response.toString().replaceAll(":null,", ":\"\","));
|
||||||
|
this.callback.onSuccess(json);
|
||||||
|
}catch(JSONException e) {
|
||||||
|
this.callback.onError();
|
||||||
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
this.callback.onError();
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send() {
|
public void send() {
|
||||||
new Thread(this).start();
|
//send sert juste a lancer la boucle principale run()
|
||||||
|
this.thread = new Thread(this);
|
||||||
|
this.thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsDelayedCall(String eventID, String eventType, DelayedCallback call) {
|
||||||
|
//on enregistre tout ce dont on a besoin pour traiter l'évenement
|
||||||
|
this.isDelayed = true;
|
||||||
|
this.delayedCallback = call;
|
||||||
|
this.eventID = eventID;
|
||||||
|
this.eventType = eventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleEvent(Event e) {
|
||||||
|
//si on est un appel delayed et que l'évenement est le bon, on lance le delayedCallback
|
||||||
|
if(this.isDelayed && e.getObjectId() == this.eventID && e.getEventType() == this.eventType) {
|
||||||
|
Pair<String,HashMap<String,String>> returned = this.delayedCallback.call();
|
||||||
|
if(this.method == "GET") {
|
||||||
|
try {
|
||||||
|
//on met a jour la connection HTTP avec la nouvelle URL en gardant l'ancienne méthode HTTP
|
||||||
|
HttpURLConnection newConnection = (HttpURLConnection) new URL(returned.getKey()).openConnection();
|
||||||
|
newConnection.setRequestMethod(this.connection.getRequestMethod());
|
||||||
|
newConnection.setDoOutput(this.connection.getDoOutput());
|
||||||
|
this.connection = newConnection;
|
||||||
|
//on a fini de mettre a jour la connection, le thread principal peut reprendre
|
||||||
|
synchronized(this.thread) {
|
||||||
|
this.thread.notify();
|
||||||
|
}
|
||||||
|
} catch (IOException e1) {
|
||||||
|
//une erreur est survenue, on stope tout
|
||||||
|
this.callback.onError();
|
||||||
|
this.shouldStop = true;
|
||||||
|
synchronized(this.thread) {
|
||||||
|
this.thread.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
//TODO: implémenter les param POST
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
this.callback.onError();
|
||||||
|
this.shouldStop = true;
|
||||||
|
synchronized(this.thread) {
|
||||||
|
this.thread.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package Classes;
|
||||||
|
|
||||||
|
public enum Category {
|
||||||
|
business, entertainment, gaming, general, healthAndMedical, music, politics, scienceAndNature, sport, technology, all
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package Classes;
|
||||||
|
|
||||||
|
public enum Languages {
|
||||||
|
fr,en
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package Classes;
|
||||||
|
|
||||||
|
public enum SortTypes {
|
||||||
|
relevancy, popularity, publishedAt
|
||||||
|
}
|
|
@ -1,7 +1,11 @@
|
||||||
package Interfaces;
|
package Interfaces;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
|
|
||||||
public void call(String response);
|
public void onSuccess(JSONObject response);
|
||||||
|
|
||||||
|
public void onError();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package Interfaces;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
|
public interface DelayedCallback {
|
||||||
|
|
||||||
|
public Pair<String,HashMap<String,String>> call();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lucas
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface Observable {
|
||||||
|
|
||||||
|
public void addObserver(String key , EventObserver o);
|
||||||
|
public void removeObserver(String key);
|
||||||
|
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ public class HeaderMenu{
|
||||||
menuItem.setOnMousePressed(new EventHandler<MouseEvent>() {
|
menuItem.setOnMousePressed(new EventHandler<MouseEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(MouseEvent event) {
|
public void handle(MouseEvent event) {
|
||||||
HeaderMenu.this.observer.handleEvent(new Classes.Event(menuItem.getId(),"click"));
|
HeaderMenu.this.observer.handleEvent(new Classes.Event(menuItem.getId(),"changeMainLayout"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ import java.util.HashMap;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import Classes.ApiCall;
|
import Classes.ApiCall;
|
||||||
|
import Classes.Category;
|
||||||
|
import Classes.Languages;
|
||||||
|
import Classes.SortTypes;
|
||||||
import Classes.css.user.ContextBuilder;
|
import Classes.css.user.ContextBuilder;
|
||||||
import Classes.css.user.Header;
|
import Classes.css.user.Header;
|
||||||
import Classes.css.user.MenuContainer;
|
import Classes.css.user.MenuContainer;
|
||||||
|
@ -15,9 +18,12 @@ import Interfaces.EventObserver;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.MenuBar;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.FlowPane;
|
import javafx.scene.layout.FlowPane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import model.LangModel;
|
||||||
|
import model.NewsListModel;
|
||||||
|
|
||||||
public class RootLayout extends Application implements EventObserver {
|
public class RootLayout extends Application implements EventObserver {
|
||||||
|
|
||||||
|
@ -64,9 +70,6 @@ public class RootLayout extends Application implements EventObserver {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void loadRootLayout(){
|
public void loadRootLayout(){
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
@ -97,28 +100,53 @@ public class RootLayout extends Application implements EventObserver {
|
||||||
launch(args);
|
launch(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(Event e) {
|
public void handleEvent(Event e) {
|
||||||
|
/*
|
||||||
HashMap<String,String> headers = new HashMap<String,String>();
|
HashMap<String,String> headers = new HashMap<String,String>();
|
||||||
headers.put("Referer", "http://www.wordreference.com");
|
headers.put("Referer", "http://www.wordreference.com");
|
||||||
|
|
||||||
ApiCall call = new ApiCall("http://api.wordreference.com/1/json/enfr/grin","GET",new Callback() {
|
ApiCall call = new ApiCall("http://api.wordreference.com/1/json/enfr/grin","GET",new Callback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void call(String response) {
|
public void onSuccess(JSONObject response) {
|
||||||
JSONObject json = new JSONObject(response);
|
System.out.println(response.toString());
|
||||||
System.out.println(json.toString());
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError() {
|
||||||
|
System.out.println("APICall error");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
call.addHeaders(headers);
|
call.addHeaders(headers);
|
||||||
call.send();
|
call.send();*/
|
||||||
|
|
||||||
System.out.println("Object "+e.getObjectId()+" fired a "+e.getEventType()+" event");
|
switch(e.getEventType()){
|
||||||
|
case "changeMainLayout":
|
||||||
|
this.handleMainLayoutChange(e.getObjectId());
|
||||||
|
break;
|
||||||
|
case "NewsQuerySuccess":
|
||||||
|
System.out.println(NewsListModel.getInstance().getNews().size()+" News ont été trouvé");
|
||||||
|
if(NewsListModel.getInstance().getNews().size() != 0) {
|
||||||
|
System.out.println("La description du premier article est: "+NewsListModel.getInstance().getNews().get(0).getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "NewsQueryFailed":
|
||||||
|
System.out.println("une erreur est survenue");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMainLayoutChange(String layout) {
|
||||||
|
NewsListModel.getInstance().addObserver("MainClass", this);
|
||||||
|
NewsListModel.getInstance().setCategory(Category.business);
|
||||||
|
NewsListModel.getInstance().setSortType(SortTypes.publishedAt);
|
||||||
|
NewsListModel.getInstance().query("bitcoin");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package model;
|
||||||
|
|
||||||
|
import Classes.Languages;
|
||||||
|
|
||||||
|
public class LangModel {
|
||||||
|
|
||||||
|
private static LangModel instance;
|
||||||
|
|
||||||
|
private Languages fromLang = Languages.fr;
|
||||||
|
private Languages toLang = Languages.en;
|
||||||
|
|
||||||
|
|
||||||
|
private LangModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LangModel getInstance() {
|
||||||
|
if(LangModel.instance == null) {
|
||||||
|
LangModel.instance = new LangModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LangModel.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFromLang(Languages lang) {
|
||||||
|
this.fromLang = lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Languages getFromLang() {
|
||||||
|
return this.fromLang;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToLang(Languages lang) {
|
||||||
|
this.toLang = lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Languages getToLang() {
|
||||||
|
return this.toLang;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
package model;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import Classes.ApiCall;
|
||||||
|
import Classes.Category;
|
||||||
|
import Classes.Event;
|
||||||
|
import Classes.SortTypes;
|
||||||
|
import Interfaces.Callback;
|
||||||
|
import Interfaces.DelayedCallback;
|
||||||
|
import Interfaces.EventObserver;
|
||||||
|
import Interfaces.Observable;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
|
public class NewsListModel implements Observable{
|
||||||
|
|
||||||
|
//instance du singleton
|
||||||
|
private static NewsListModel instance;
|
||||||
|
|
||||||
|
//Clé d'API
|
||||||
|
private String APIKey;
|
||||||
|
//catégorie choise parl'utilisateur
|
||||||
|
private Category cat = Category.all;
|
||||||
|
//est ce que le modele est en train de récupérer les sources
|
||||||
|
private Boolean isRetreivingSources = false;
|
||||||
|
//est ce que l'api a rencontré une erreur
|
||||||
|
private Boolean apiError = false;
|
||||||
|
//liste des sources
|
||||||
|
private ArrayList<String> sources;
|
||||||
|
//liste des observers
|
||||||
|
private HashMap<String,EventObserver> observers;
|
||||||
|
//liste des news finale
|
||||||
|
private ArrayList<NewsModel> news;
|
||||||
|
//critère de tri
|
||||||
|
private SortTypes sortType = SortTypes.relevancy;
|
||||||
|
//critère de recherche de l'utilisateur
|
||||||
|
private String query = "";
|
||||||
|
|
||||||
|
private NewsListModel(String APIKey) {
|
||||||
|
this.APIKey = APIKey;
|
||||||
|
//comme la liste des sources retournée par l'API est de 20 éléments max, pas la peine de déclarer une arraylist sans borne
|
||||||
|
this.sources = new ArrayList<String>(20);
|
||||||
|
this.observers = new HashMap<String,EventObserver>();
|
||||||
|
this.news = new ArrayList<NewsModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NewsListModel getInstance() {
|
||||||
|
if(NewsListModel.instance == null) {
|
||||||
|
NewsListModel.instance = new NewsListModel("0e72f765c5c84313ae31a5a7e9e61735");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewsListModel.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(Category cat) {
|
||||||
|
|
||||||
|
if(cat == Category.all) {
|
||||||
|
this.sources = null;
|
||||||
|
this.cat = cat;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//on vide la liste des sources
|
||||||
|
this.sources = new ArrayList<String>(20);
|
||||||
|
this.cat = cat;
|
||||||
|
//on créé l'URL d'appel de l'API
|
||||||
|
String lang = LangModel.getInstance().getToLang().name();
|
||||||
|
String URL = "http://beta.newsapi.org/v2/sources?language="+lang;
|
||||||
|
|
||||||
|
//on rajoute la catégorie
|
||||||
|
if(cat != Category.all) {
|
||||||
|
URL += "&category="+cat.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
//on rajoute la clé d'api
|
||||||
|
URL += "&apiKey="+this.APIKey;
|
||||||
|
|
||||||
|
//création de l'appel
|
||||||
|
ApiCall api = new ApiCall(URL,"GET",new Callback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject response) {
|
||||||
|
//on récupère toutes les sources (dans la limite de 20 sources)
|
||||||
|
JSONArray arr = response.getJSONArray("sources");
|
||||||
|
for(int i = 0;i<arr.length() && i<20;i++) {
|
||||||
|
NewsListModel.this.sources.add(((JSONObject)arr.get(i)).getString("id"));
|
||||||
|
}
|
||||||
|
NewsListModel.this.isRetreivingSources = false;
|
||||||
|
NewsListModel.this.apiError = false;
|
||||||
|
//tout s'est bien passé, on peut notifier du succès
|
||||||
|
NewsListModel.this.notifyObservers(new Event("NewsModel","SourcesUpdated"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError() {
|
||||||
|
//on notifie de l'échec et on garde en mémoire le fait que l'on a échoué (afin d'annuler la recherche de news qui va suivre)
|
||||||
|
NewsListModel.this.isRetreivingSources = false;
|
||||||
|
NewsListModel.this.apiError = true;
|
||||||
|
NewsListModel.this.notifyObservers(new Event("NewsModel","SourcesUpdateFailed"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
this.isRetreivingSources = true;
|
||||||
|
api.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category getCategory() {
|
||||||
|
return this.cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void query(String q) {
|
||||||
|
//si la recherche de source s'est fini avec une erreur, pas la peine de chercher des articles
|
||||||
|
if(this.apiError) {
|
||||||
|
NewsListModel.this.notifyObservers(new Event("NewsModel","NewsQueryFailed"));
|
||||||
|
this.apiError = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//on créer l'URL de l'appel
|
||||||
|
String lang = LangModel.getInstance().getToLang().name();
|
||||||
|
String URL = "http://beta.newsapi.org/v2/everything?apiKey="+this.APIKey+"&language="+lang+"&q="+q+"&sortBy="+this.sortType.name();
|
||||||
|
|
||||||
|
//on ajoute la liste des sources a l'URL de la requete
|
||||||
|
if(NewsListModel.this.sources != null && NewsListModel.this.sources.size() != 0) {
|
||||||
|
String sources = "&sources=";
|
||||||
|
for(String s : NewsListModel.this.sources) {
|
||||||
|
sources += s+",";
|
||||||
|
}
|
||||||
|
//on enlève la dernière virgule
|
||||||
|
sources = sources.replaceAll(",$", "");
|
||||||
|
URL += sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiCall api = new ApiCall(URL,"GET",new Callback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject response) {
|
||||||
|
//on parcours le JSON en créant les objets NewsModel corespondant
|
||||||
|
NewsListModel.this.news = new ArrayList<NewsModel>();
|
||||||
|
JSONArray arr = response.getJSONArray("articles");
|
||||||
|
for(int i = 0;i<arr.length();i++) {
|
||||||
|
JSONObject jsonNews = (JSONObject)arr.get(i);
|
||||||
|
NewsModel news = new NewsModel();
|
||||||
|
news.setAuthor(jsonNews.getString("author"))
|
||||||
|
.setDescription(jsonNews.getString("description"))
|
||||||
|
.setTitle(jsonNews.getString("title"))
|
||||||
|
.setNewsURL(jsonNews.getString("url"))
|
||||||
|
.setImageURL(jsonNews.getString("urlToImage"))
|
||||||
|
.setSource(jsonNews.getJSONObject("source").getString("name"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
news.setDate(jsonNews.getString("publishedAt"));
|
||||||
|
}catch (ParseException e) {
|
||||||
|
news.setDate(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
NewsListModel.this.news.add(news);
|
||||||
|
}
|
||||||
|
|
||||||
|
NewsListModel.this.query = q;
|
||||||
|
//ne pas oublier d'enlever l'api des observer, sinon il y a des risques de récurrence
|
||||||
|
NewsListModel.this.removeObserver("newsApiCall");
|
||||||
|
NewsListModel.this.notifyObservers(new Event("NewsModel","NewsQuerySuccess"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError() {
|
||||||
|
//L'appel a échoué :(
|
||||||
|
System.out.println("Error");
|
||||||
|
NewsListModel.this.removeObserver("newsApiCall");
|
||||||
|
NewsListModel.this.notifyObservers(new Event("NewsModel","NewsQueryFailed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//on delay uniquement si on est en train de récupérer les sources
|
||||||
|
if(this.isRetreivingSources) {
|
||||||
|
api.setAsDelayedCall("NewsModel", "SourcesUpdated", new DelayedCallback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pair<String, HashMap<String, String>> call() {
|
||||||
|
//si l'appel d'api précédent a échoué, on fait échouer l'appel actuel avec une URL vide
|
||||||
|
if(NewsListModel.this.apiError) {
|
||||||
|
//on reset la variable d'erreur pour que l'utilisateur puisse re-essayer plus tard
|
||||||
|
NewsListModel.this.apiError = false;
|
||||||
|
return new Pair<String,HashMap<String,String>>("",null);
|
||||||
|
}
|
||||||
|
|
||||||
|
String lang = LangModel.getInstance().getToLang().name();
|
||||||
|
String URL = "http://beta.newsapi.org/v2/everything?apiKey="+NewsListModel.this.APIKey+"&language="+lang
|
||||||
|
+"&q="+q+"&sortBy="+NewsListModel.this.sortType.name();
|
||||||
|
|
||||||
|
//on ajoute la liste des sources a l'URL de la requete
|
||||||
|
if(NewsListModel.this.sources != null && NewsListModel.this.sources.size() != 0) {
|
||||||
|
String sources = "&sources=";
|
||||||
|
for(String s : NewsListModel.this.sources) {
|
||||||
|
sources += s+",";
|
||||||
|
}
|
||||||
|
//on enlève la dernière virgule
|
||||||
|
sources = sources.replaceAll(",$", "");
|
||||||
|
URL += sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pair<String,HashMap<String,String>>(URL,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addObserver("newsApiCall",api);
|
||||||
|
}
|
||||||
|
|
||||||
|
api.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSortType(SortTypes t) {
|
||||||
|
this.sortType = t;
|
||||||
|
this.query(this.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyObservers(Event e) {
|
||||||
|
for(Object key : this.observers.keySet().toArray()) {
|
||||||
|
this.observers.get(key).handleEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<NewsModel> getNews(){
|
||||||
|
return this.news;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addObserver(String key, EventObserver o) {
|
||||||
|
this.observers.put(key, o);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeObserver(String key) {
|
||||||
|
this.observers.remove(key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package model;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class NewsModel {
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
private String source;
|
||||||
|
private String imageURL;
|
||||||
|
private String newsURL;
|
||||||
|
private String title;
|
||||||
|
private String description;
|
||||||
|
private Date date;
|
||||||
|
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
public NewsModel setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
public NewsModel setSource(String source) {
|
||||||
|
this.source = source;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public String getImageURL() {
|
||||||
|
return imageURL;
|
||||||
|
}
|
||||||
|
public NewsModel setImageURL(String imageURL) {
|
||||||
|
this.imageURL = imageURL;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public String getNewsURL() {
|
||||||
|
return newsURL;
|
||||||
|
}
|
||||||
|
public NewsModel setNewsURL(String newsURL) {
|
||||||
|
this.newsURL = newsURL;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
public NewsModel setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
public NewsModel setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
public NewsModel setDate(String date) throws ParseException {
|
||||||
|
//on déclare le format de date
|
||||||
|
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
|
||||||
|
date = date.replace("Z", "+0000");
|
||||||
|
this.date = fmt.parse(date);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NewsModel setDate(Date date){
|
||||||
|
this.date = date;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue