read config from json. Many refactoring to prepare multi language support
authorJean-Philippe Orsini <orsinije@fr.ibm.com>
Wed, 25 Oct 2017 23:10:18 +0000 (01:10 +0200)
committerJean-Philippe Orsini <orsinije@fr.ibm.com>
Wed, 25 Oct 2017 23:10:18 +0000 (01:10 +0200)
war/src/main/java/pnews/Category.java
war/src/main/java/pnews/servlet/ArticleProvider.java
war/src/main/java/pnews/servlet/Config.java
war/src/main/java/pnews/servlet/HTML.java
war/src/main/java/pnews/servlet/JSON.java
war/src/main/java/pnews/servlet/Pnews.java
war/src/main/resources/feeds.json

index 6656ea7..1156acf 100644 (file)
@@ -1,27 +1,26 @@
 package pnews;
 
-public enum Category {
-        ACTUALITE("Les actualités à la une"),
-        FRANCE("France"),
-        SPORT("Sport"),
-        EUROPE("Europe"),
-        MONDE("Monde"),
-        ECONOMIE("Economie"),
-        ESSONNE("Essonne"),
-        TECHNOLOGIE("Technologie"),
-        PEOPLE("People");
-        
-        private final String title;
+public class Category {
+        private final String name;
+                
+        public Category(String name) {
+                this.name = name;
+        }
                 
-        private Category(String title) {
-                this.title = title;
+        public String getTitle() {
+                return name;
         }
         
-        public String getId() {
-                return name();
+        public String getURL() {
+                return "/fr/" + name.toLowerCase();
         }
         
-        public String getTitle() {
-                return title;
+        public String getName() {
+                return name;
+        }        
+        
+        @Override
+        public String toString() {
+                return getName();
         }
 }
index 48c551b..3e90d11 100644 (file)
@@ -27,15 +27,17 @@ import com.rometools.rome.io.XmlReader;
 
 import pnews.Article;
 import pnews.Category;
+import pnews.Feed;
 
 public class ArticleProvider {
-        public final static ArticleProvider singleton = new ArticleProvider();
         private static final Logger LOG = Logger.getLogger(ArticleProvider.class.getName());
         private final Map<Category, List<Article>> articlesByCategory = new HashMap<>();
         private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
+        private final Config config;
         
-        private ArticleProvider() {      
-                for (Category cat:Category.values())
+        public ArticleProvider(Config config) {
+                this.config = config;
+                for (Category cat: config.getCategories())
                         scheduler.scheduleAtFixedRate(new Refresher(cat), 2, 600, TimeUnit.SECONDS);
         }
         
@@ -47,8 +49,6 @@ public class ArticleProvider {
                 return new SyndFeedInput().build(r);                
         }
         
-        
-        
         private List<Article> getArticlesForUpdate(Category cat) {
                 List<Article> result;
                 
@@ -117,7 +117,7 @@ public class ArticleProvider {
                 
                 feedTitle = feed.getTitle().trim();
                 
-                LOG.info("addArticles " + cat.getId() + " " + feedTitle + " number of articles: " + feed.getEntries().size());
+                LOG.info("addArticles " + cat.getName() + " " + feedTitle + " number of articles: " + feed.getEntries().size());
                 
                 for (SyndEntry entry: feed.getEntries()) {
                         String link = entry.getLink().trim();
@@ -147,21 +147,21 @@ public class ArticleProvider {
                         }
                 }          
                 
-                LOG.info("addArticles done " + cat.getId());
+                LOG.info("addArticles done " + cat.getName());
         }
              
         private void retrieveArticles(Category cat) throws IllegalArgumentException, MalformedURLException, FeedException, IOException {
-                String[] feeds;
+                List<Feed> feeds;
                 
-                feeds = Config.getFeedsByCategory().get(cat);
+                feeds = config.getFeedsByCategory().get(cat);
                 
                 if (feeds != null)
-                        for (String str: feeds)
+                        for (Feed f: feeds)
                                 try {
-                                        addArticles(cat, getSyndFeed(str));
+                                        addArticles(cat, getSyndFeed(f.getURL()));
                                 } catch (Throwable e) {
                                         LOG.log(Level.SEVERE,
-                                                "retrieveArticles failure " + cat.getId() + " " + str,
+                                                "retrieveArticles failure " + cat.getName() + " " + f.toString(),
                                                 e);
                                 }
                 else
@@ -193,7 +193,7 @@ public class ArticleProvider {
                 
                 @Override
                 public void run() {                       
-                        LOG.info("refresher "+ category.getId());
+                        LOG.info("refresher "+ category.getName());
                         
                         try {
                                 retrieveArticles(category);
@@ -201,7 +201,7 @@ public class ArticleProvider {
                                 LOG.log(Level.SEVERE, "refresher failure", e);
                         }                        
                         
-                        LOG.info("refresher "+ category.getId() + " done");
+                        LOG.info("refresher "+ category.getName() + " done");
                 }                
         }
 }
index 5c0c134..a77eb88 100644 (file)
@@ -16,101 +16,100 @@ import pnews.Category;
 import pnews.Feed;
 
 public class Config {
-        public static Feed[] getFeeds() {
+        private Feed[] feeds;
+        private Category[] categories;
+                
+        public void loadConfig() {
                 Reader r;
-                List<Feed> feeds;
-                JsonObject jfeeds;
+                JsonObject jfeeds, jroot;
+                List<Feed> feedList;
+                Map<String, Category> cats;
                 
                 r = null;
                 try {
                         r = new InputStreamReader(Config.class.getClassLoader().getResourceAsStream("feeds.json"));
-                        jfeeds = Json.createReader(r).readObject();
+                        jroot = Json.createReader(r).readObject();
                 } finally {
                         if (r != null)
                                 try { r.close(); } catch (IOException e) { };
                 }
                 
-                feeds = new ArrayList<Feed>(jfeeds.size());
+                jfeeds = jroot.getJsonObject("feeds");
+                
+                feedList = new ArrayList<Feed>(jfeeds.size());
+                cats = new HashMap<>();
 
                 jfeeds.forEach((k, v)-> {
                         JsonObject jf;
+                        String str;
+                        Category cat;
                         JsonArray jcategories;
                         
                         jf = (JsonObject)v;
                         jcategories = jf.getJsonArray("categories");
-                        feeds.add(new Feed(k, Category.valueOf(jcategories.getString(0))));
-                });
+                        str = jcategories.getString(0);
+                        
+                        cat = cats.get(str);
+                        if (cat == null) {
+                                cat = new Category(str);
+                                cats.put(str, cat);
+                        }
                         
-                return feeds.toArray(new Feed[] {});
+                        feedList.add(new Feed(k, cat));                                           
+                });
+                
+                feeds = feedList.toArray(new Feed[0]);
+                categories = cats.values().toArray(new Category[0]);
+        }
+        
+        public Feed[] getFeeds() {
+                return feeds;
         }
         
-        public static Map<Category, String[]> getFeedsByCategory() {
-                Map<Category, String[]> result;
+        public Map<Category, List<Feed>> getFeedsByCategory() {
+                Map<Category, List<Feed>> result;
+                Feed[] feeds;
+                List<Feed> catFeeds;
+                Category cat;
                 
                 result = new HashMap<>();
                 
-                result.put(Category.ACTUALITE,
-                           new String[] {
-                                           "http://www.europe1.fr/var/export/rss/europe1/actus.xml",
-                                           "http://www.francetvinfo.fr/titres.rss",
-                                           "http://www.rfi.fr/general/rss",
-                                           "http://www.cnews.fr/rss/une",
-                                           "http://www.ladepeche.fr/rss/a-la-une.rss",
-                                           "https://www.franceinter.fr/rss/a-la-une.xml",
-                                           "https://www.francebleu.fr/rss/a-la-une.xml",
-                                           "http://www.bfmtv.com/rss/info/flux-rss/flux-toutes-les-actualites/"
-                           });
-                
-                result.put(Category.SPORT,
-                                new String[] { "http://www.europe1.fr/var/export/rss/europe1/sport.xml",
-                                               "http://www.sportune.fr/feed",
-                                               "http://www.france24.com/fr/sports/rss" });
-                
-                result.put(Category.FRANCE,
-                                new String[] { "http://www.france24.com/fr/france/rss",
-                                               "http://www.francetvinfo.fr/france.rss",
-                                               "http://www.rfi.fr/france/rss"});
-                
-                result.put(Category.EUROPE,
-                                new String[] { "http://www.france24.com/fr/europe/rss" });
-
-                result.put(Category.MONDE, 
-                           new String[] { "http://www.europe1.fr/var/export/rss/europe1/international.xml",
-                                          "http://www.france24.com/fr/actualites/rss" });                                           
-
-                
-                result.put(Category.ECONOMIE,
-                                new String[] { "http://www.france24.com/fr/economie/rss",
-                                               "http://www.europe1.fr/var/export/rss/europe1/economie.xml",
-                                               "http://www.rfi.fr/economie/rss" });
-                
-                result.put(Category.ESSONNE,
-                                new String[] { "http://www.tourisme-essonne.com/rss/actus/",
-                                               "http://www.ville-palaiseau.fr/rss/actualites.htm" });
-                
-                result.put(Category.PEOPLE,
-                                new String[] { "http://www.premiere.fr/rss/actu-live",
-                                               "http://www.purepeople.com/rss/news_t0.xml"                                               
-                });
+                feeds = getFeeds();
+                for (Feed f: feeds) {
+                        cat = f.getCategory();
                 
-                result.put(Category.TECHNOLOGIE,
-                                new String[] { "http://www.generation-nt.com/export/rss.xml",
-                                               "http://www.europe1.fr/var/export/rss/europe1/sciences.xml",
-                                               "http://feeds.feedburner.com/lesnumeriques/news",
-                                               "http://www.zdnet.fr/feeds/rss/actualites/",
-                                               "http://www.frandroid.com/feed",
-                                               "http://www.silicon.fr/feed",
-                                               "http://www.fredzone.org/feed",
-                                               "http://www.futura-sciences.com/rss/actualites.xml",
-                                               "https://www-03.ibm.com/press/fr/fr/rssfeed.wss?keyword=null&maxFeed=&feedType=RSS&topic=all"});
+                        catFeeds = result.get(cat);
+                        if (catFeeds == null) {
+                                catFeeds = new ArrayList<Feed>();
+                                result.put(cat, catFeeds);
+                        }
+                        catFeeds.add(f);
+                }
                 
                 return result;
         }
 
+        public Category[] getCategories() {
+                return categories;
+        }
+        
+        public Category getDefaultCategory() {
+                return categories[0];
+        }
+        
         public static void main(String[] args) {
-                Feed[] feeds;
+                Config cfg;
+                Feed[] feeds;           
+                Category[] cats;
+
+                cfg = new Config();
+                cfg.loadConfig();
                 
-                feeds = getFeeds();
+                cats = cfg.getCategories();
+                for (Category cat: cats)
+                        System.out.println(cat);
+                
+                feeds = cfg.getFeeds();
                 
                 System.out.println("Number of feeds: " + feeds.length);
                 for (Feed f: feeds)
index 7b7b142..e9aae26 100644 (file)
@@ -53,7 +53,7 @@ public class HTML {
                buf.append("<div class='article-content'>\n");
 
                buf.append("<div class='article-title'>\n");
-               appendA(buf, a.title, "redirect?url=" + URLEncoder.encode(a.link, "UTF-8"), null);
+               appendA(buf, a.title, "/redirect?url=" + URLEncoder.encode(a.link, "UTF-8"), null);
                buf.append("</div>\n");
                
                buf.append("<div class='article-info'>" + a.website + " - " + a.publicationDate + "</div>");
@@ -71,13 +71,13 @@ public class HTML {
                buf.append("</div>\n");         
        }
        
-       private static void appendMenu(StringBuffer buf, Category catActive) {
+       private static void appendMenu(StringBuffer buf, Category catActive, Category[] cats) {
                String cl;
                
                buf.append("<nav>\n");
                buf.append("<ul>\n");
 
-               for (Category cat: Category.values()) {
+               for (Category cat: cats) {
                        buf.append("<li>");
                        
                        if (cat.equals(catActive))
@@ -85,7 +85,7 @@ public class HTML {
                        else
                                cl = null;
                        
-                       appendA(buf, cat.getId(), cat.getId(), cl);
+                       appendA(buf, cat.getName(), cat.getURL(), cl);
                        buf.append("</li>");
                }
                
@@ -93,7 +93,7 @@ public class HTML {
                buf.append("</nav>\n");
        }
        
-       public static String toHTML(List<Article> articles, Category catActive) {
+       public static String toHTML(List<Article> articles, Category catActive, Category[] cats) {
                StringBuffer buf;
                int i;
                
@@ -102,14 +102,14 @@ public class HTML {
                buf.append("<html lang='fr'>\n");
                buf.append("<head>\n");
                buf.append("<meta charset=\"UTF-8\">\n");
-               buf.append("<link rel='stylesheet' href='style.css' />\n");
+               buf.append("<link rel='stylesheet' href='/style.css' />\n");
                buf.append("<title>");
                buf.append(catActive.getTitle());
                buf.append(" - PNews</title>\n");
                buf.append("</head>\n");
                buf.append("<body>\n");
                
-               appendMenu(buf, catActive);
+               appendMenu(buf, catActive, cats);
                
                i = 0;
                for (Article e: articles) {
index 20afaa6..0a9b8ce 100644 (file)
@@ -14,10 +14,10 @@ import pnews.Category;
 public class JSON {
         private static final Logger LOG = Logger.getLogger(JSON.class.getName());
         
-        public static String getStats() {
+        public static String getStats(Category[] cats) {
                 JsonObject jstats, jreadcounts, jcategories, jmemory;
-                Article[] articles;
                 Runtime runtime;
+                Article[] articles;
                 
                 jstats = new JsonObject();
                                 
@@ -34,10 +34,11 @@ public class JSON {
                 jcategories = new JsonObject();
                 jstats.add("categories", jcategories);
                 
-                for (Category cat: Category.values())
+                for (Category cat: cats)
                         try {
-                                jcategories.addProperty(cat.getId(), ArticleProvider.singleton.getArticles(cat).size());
-                        } catch (IllegalArgumentException | FeedException | IOException e) {
+                                jcategories.addProperty(cat.getName(),
+                                                        articles.length);
+                        } catch (IllegalArgumentException e) {
                                 LOG.log(Level.SEVERE, "Fail to retrieve articles", e);
                         }
                 
index 2e49a7a..e254a61 100644 (file)
@@ -27,7 +27,8 @@ public class Pnews extends HttpServlet {
         private static final String CLASS_NAME = Pnews.class.getName();
         private static final Logger LOG = Logger.getLogger(Pnews.class.getName());
         private static final long serialVersionUID = 1L;
-        private static final ArticleProvider provider = ArticleProvider.singleton;
+        private ArticleProvider provider;
+        private Config config;
 
         private static String getQueryParameter(HttpServletRequest rq, String key)
                         throws UnsupportedEncodingException {
@@ -94,7 +95,7 @@ public class Pnews extends HttpServlet {
                 rp.setContentType("application/json;charset=utf-8");
                 rp.setCharacterEncoding("utf-8");
 
-                rp.getWriter().write(JSON.getStats());
+                rp.getWriter().write(JSON.getStats(config.getCategories()));
         }
 
         
@@ -105,13 +106,13 @@ public class Pnews extends HttpServlet {
                 try {
                         articles = provider.getArticles(cat);
                         if (articles != null) {
-                                html = HTML.toHTML(articles, cat);
+                                html = HTML.toHTML(articles, cat, config.getCategories());
                                 rp.setContentType("text/html;charset=utf-8");
                                 rp.getWriter().write(html);
                                 rp.setCharacterEncoding("utf-8");
                         } else {
                                 LOG.severe("writeArticles cannot retrieve any articles");
-                                html = HTML.toHTML(new ArrayList<Article>(), cat);
+                                html = HTML.toHTML(new ArrayList<Article>(), cat, config.getCategories());
                                 rp.setContentType("text/html");
                                 rp.getWriter().write(html);
                         }
@@ -167,7 +168,7 @@ public class Pnews extends HttpServlet {
                 }
 
                 if (path.equals("/")) {
-                        writeArticles(Category.ACTUALITE, resp);
+                        writeArticles(config.getDefaultCategory(), resp);
                         return ;
                 }
 
@@ -178,8 +179,8 @@ public class Pnews extends HttpServlet {
                                 return ;
                         }
                 
-                        for (Category cat: Category.values()) {
-                                if (path.equals('/' + cat.getId())) {
+                        for (Category cat: config.getCategories()) {
+                                if (path.equals(cat.getURL())) {
                                         writeArticles(cat, resp);
                                         return ;
                                 }
@@ -194,8 +195,12 @@ public class Pnews extends HttpServlet {
         }
 
         @Override
-        public void init(ServletConfig config) throws ServletException {
-                LOG.info("Pnews servlet init " + config.getServletContext().getContextPath());
-
+        public void init(ServletConfig cfg) throws ServletException {
+                LOG.info("Pnews servlet init " + cfg.getServletContext().getContextPath());
+                
+                config = new Config();
+                config.loadConfig();
+                
+                provider = new ArticleProvider(config);
         }
 }
index 120bc25..f0e0916 100644 (file)
@@ -1,34 +1,37 @@
 {
-        "http://www.europe1.fr/var/export/rss/europe1/actus.xml": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "http://www.francetvinfo.fr/titres.rss":  {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "http://www.rfi.fr/general/rss": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "http://www.cnews.fr/rss/une": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "http://www.ladepeche.fr/rss/a-la-une.rss": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "https://www.franceinter.fr/rss/a-la-une.xml": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "https://www.francebleu.fr/rss/a-la-une.xml": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
-        },
-        "http://www.bfmtv.com/rss/info/flux-rss/flux-toutes-les-actualites/": {
-                "categories": ["ACTUALITE"],
-                "language": "fr"
+        "feeds": {
+                "http://www.europe1.fr/var/export/rss/europe1/actus.xml": { "categories": ["ACTUALITE"] },
+                "http://www.francetvinfo.fr/titres.rss":  { "categories": ["ACTUALITE"] },
+                "http://www.rfi.fr/general/rss": { "categories": ["ACTUALITE"] },
+                "http://www.cnews.fr/rss/une": { "categories": ["ACTUALITE"] },
+                "http://www.ladepeche.fr/rss/a-la-une.rss": { "categories": ["ACTUALITE"] },
+                "https://www.franceinter.fr/rss/a-la-une.xml": { "categories": ["ACTUALITE"] },
+                "https://www.francebleu.fr/rss/a-la-une.xml": { "categories": ["ACTUALITE"] },
+                "http://www.bfmtv.com/rss/info/flux-rss/flux-toutes-les-actualites/": { "categories": ["ACTUALITE"] },
+                "http://www.europe1.fr/var/export/rss/europe1/sport.xml": { "categories": ["SPORT"] },
+                "http://www.sportune.fr/feed": { "categories": ["SPORT"] },
+                "http://www.france24.com/fr/sports/rss": { "categories": ["SPORT"] },
+                "http://www.france24.com/fr/france/rss": { "categories": ["FRANCE"] },
+                "http://www.francetvinfo.fr/france.rss": { "categories": ["FRANCE"] },
+                "http://www.rfi.fr/france/rss": { "categories": ["FRANCE"] },
+                "http://www.france24.com/fr/europe/rss": { "categories": ["EUROPE"] },
+                "http://www.europe1.fr/var/export/rss/europe1/international.xml": { "categories": ["MONDE"] },
+                "http://www.france24.com/fr/actualites/rss": { "categories": ["MONDE"] },
+                "http://www.france24.com/fr/economie/rss": { "categories": ["ECONOMIE"] },
+                "http://www.europe1.fr/var/export/rss/europe1/economie.xml": { "categories": ["ECONOMIE"] },
+                "http://www.rfi.fr/economie/rss": { "categories": ["ECONOMIE"] },
+                "http://www.tourisme-essonne.com/rss/actus/": { "categories": ["ESSONNE"] },
+                "http://www.ville-palaiseau.fr/rss/actualites.htm": { "categories": ["ESSONNE"] },
+                "http://www.premiere.fr/rss/actu-live": { "categories": ["PEOPLE"] },
+                "http://www.purepeople.com/rss/news_t0.xml": { "categories": ["PEOPLE"] },
+                "http://www.generation-nt.com/export/rss.xml": { "categories": ["TECHNOLOGIE"] },
+                "http://www.europe1.fr/var/export/rss/europe1/sciences.xml": { "categories": ["TECHNOLOGIE"] },
+                "http://feeds.feedburner.com/lesnumeriques/news": { "categories": ["TECHNOLOGIE"] },
+                "http://www.zdnet.fr/feeds/rss/actualites/": { "categories": ["TECHNOLOGIE"] },
+                "http://www.frandroid.com/feed": { "categories": ["TECHNOLOGIE"] },
+                "http://www.silicon.fr/feed": { "categories": ["TECHNOLOGIE"] },
+                "http://www.fredzone.org/feed": { "categories": ["TECHNOLOGIE"] },
+                "http://www.futura-sciences.com/rss/actualites.xml": { "categories": ["TECHNOLOGIE"] },
+                "https://www-03.ibm.com/press/fr/fr/rssfeed.wss?keyword=null&maxFeed=&feedType=RSS&topic=all": { "categories": ["TECHNOLOGIE"] }
         }
 }