diff --git a/src/main/java/org/jboss/forge/website/SiteConstants.java b/src/main/java/org/jboss/forge/website/SiteConstants.java index 7de3e3c..70fe3b6 100644 --- a/src/main/java/org/jboss/forge/website/SiteConstants.java +++ b/src/main/java/org/jboss/forge/website/SiteConstants.java @@ -16,6 +16,7 @@ public interface SiteConstants String ADDON_REPO_URL_CORE = REPO_BASE_URL + "/addons-core.yaml"; String ADDON_REPO_URL_COMMUNITY = REPO_BASE_URL + "/addons-community.yaml"; + String DOCS_REPO_URL_NEWS = REPO_BASE_URL + "/docs-news.yaml"; String DOCS_REPO_URL_GETSTARTED = REPO_BASE_URL + "/docs-getstarted.yaml"; String DOCS_REPO_URL_TUTORIALS = REPO_BASE_URL + "/docs-tutorials.yaml"; String DOCS_REPO_URL_ADVANCED = REPO_BASE_URL + "/docs-advanced.yaml"; diff --git a/src/main/java/org/jboss/forge/website/model/News.java b/src/main/java/org/jboss/forge/website/model/News.java new file mode 100644 index 0000000..25b16a2 --- /dev/null +++ b/src/main/java/org/jboss/forge/website/model/News.java @@ -0,0 +1,151 @@ +package org.jboss.forge.website.model; + +import java.io.Serializable; +import java.util.Date; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class News implements Serializable +{ + private static final long serialVersionUID = 1L; + private String title; + private String summary; + private String repo; + private String ref; + private String path; + private String author; + private String email; + private Date date; + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getSummary() + { + return summary; + } + + public void setSummary(String summary) + { + this.summary = summary; + } + + public String getRepo() + { + return repo; + } + + public void setRepo(String repository) + { + this.repo = repository; + } + + public String getRef() + { + return ref; + } + + public void setRef(String ref) + { + this.ref = ref; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public String getAuthor() + { + return author; + } + + public void setAuthor(String author) + { + this.author = author; + } + + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + public Date getDate() + { + return date; + } + + public void setDate(Date date) + { + this.date = date; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((ref == null) ? 0 : ref.hashCode()); + result = prime * result + ((repo == null) ? 0 : repo.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + News other = (News) obj; + if (path == null) + { + if (other.path != null) + return false; + } + else if (!path.equals(other.path)) + return false; + if (ref == null) + { + if (other.ref != null) + return false; + } + else if (!ref.equals(other.ref)) + return false; + if (repo == null) + { + if (other.repo != null) + return false; + } + else if (!repo.equals(other.repo)) + return false; + return true; + } + + @Override + public String toString() + { + return repo + " " + ref + " " + path; + } +} \ No newline at end of file diff --git a/src/main/java/org/jboss/forge/website/rewrite/RouteConfiguration.java b/src/main/java/org/jboss/forge/website/rewrite/RouteConfiguration.java index 5843f19..1907cf6 100644 --- a/src/main/java/org/jboss/forge/website/rewrite/RouteConfiguration.java +++ b/src/main/java/org/jboss/forge/website/rewrite/RouteConfiguration.java @@ -56,7 +56,10 @@ public Configuration getConfiguration(ServletContext context) .addRule(Join.path("/document/{title}").to("/document").withChaining()) .where("title").transposedBy(new SpacesToDashes()) - + + .addRule(Join.path("/news/{title}").to("/news-entry").withChaining()) + .where("title").transposedBy(new SpacesToDashes()) + .addRule(Join.path("/addon/{id}").to("/addon").withChaining()) /* diff --git a/src/main/java/org/jboss/forge/website/service/RepositoryService.java b/src/main/java/org/jboss/forge/website/service/RepositoryService.java index 8203cd7..2860186 100644 --- a/src/main/java/org/jboss/forge/website/service/RepositoryService.java +++ b/src/main/java/org/jboss/forge/website/service/RepositoryService.java @@ -19,6 +19,7 @@ import org.jboss.forge.website.model.Addon.Category; import org.jboss.forge.website.model.Contributor; import org.jboss.forge.website.model.Document; +import org.jboss.forge.website.model.News; import org.yaml.snakeyaml.Yaml; import com.google.gson.Gson; @@ -37,14 +38,14 @@ public List getAllAddons() { List result = new ArrayList<>(); - List community = fetchList(SiteConstants.ADDON_REPO_URL_COMMUNITY, Addon.class); + List community = fetchYamlList(SiteConstants.ADDON_REPO_URL_COMMUNITY, Addon.class); for (Addon addon : community) { addon.setCategory(Category.COMMUNITY); } result.addAll(community); - List core = fetchList(SiteConstants.ADDON_REPO_URL_CORE, Addon.class); + List core = fetchYamlList(SiteConstants.ADDON_REPO_URL_CORE, Addon.class); for (Addon addon : core) { addon.setCategory(Category.CORE); @@ -57,7 +58,7 @@ public List getAllAddons() public List getRandomCommunityAddons(int count) { List result = new ArrayList<>(); - List addons = new ArrayList<>(fetchList(SiteConstants.ADDON_REPO_URL_COMMUNITY, Addon.class)); + List addons = new ArrayList<>(fetchYamlList(SiteConstants.ADDON_REPO_URL_COMMUNITY, Addon.class)); Random random = new Random(System.currentTimeMillis()); while (result.size() < count && !addons.isEmpty()) @@ -72,21 +73,21 @@ public List getAllDocuments() { List result = new ArrayList<>(); - List getStarted = fetchList(SiteConstants.DOCS_REPO_URL_GETSTARTED, Document.class); + List getStarted = fetchYamlList(SiteConstants.DOCS_REPO_URL_GETSTARTED, Document.class); for (Document document : getStarted) { document.setCategory(org.jboss.forge.website.model.Document.Category.QUICKSTART); } result.addAll(getStarted); - List tutorials = fetchList(SiteConstants.DOCS_REPO_URL_TUTORIALS, Document.class); + List tutorials = fetchYamlList(SiteConstants.DOCS_REPO_URL_TUTORIALS, Document.class); for (Document document : tutorials) { document.setCategory(org.jboss.forge.website.model.Document.Category.TUTORIAL); } result.addAll(tutorials); - List advanced = fetchList(SiteConstants.DOCS_REPO_URL_ADVANCED, Document.class); + List advanced = fetchYamlList(SiteConstants.DOCS_REPO_URL_ADVANCED, Document.class); for (Document document : advanced) { document.setCategory(org.jboss.forge.website.model.Document.Category.ADVANCED); @@ -137,73 +138,78 @@ public List getAllContributors() return Arrays.asList(contributors); } - /* - * Helpers - */ - - private List parse(String content, Class type) + public List getRelatedDocuments(Addon addon, int count) { - List result = new ArrayList<>(); + List result = new ArrayList<>(); - if (content != null) + String tagString = addon.getTags(); + if (tagString != null && !tagString.isEmpty()) { - List addonEntries = Arrays.asList(content.trim().split("---")); - - for (String addonEntry : addonEntries) + for (String tag : tagString.split(",")) { - if (!addonEntry.trim().isEmpty()) + tag = tag.trim(); + for (Document doc : getAllDocuments()) { - T addon = new Yaml().loadAs(addonEntry, type); - result.add(addon); + if ((doc.getSummary() != null && doc.getSummary().contains(tag)) + || (doc.getSummary() != null && doc.getTitle().contains(tag))) + { + result.add(doc); + } } } } - return result; + return new ArrayList(); + } + + public List getAllNews() + { + List news = fetchYamlList(SiteConstants.DOCS_REPO_URL_NEWS, News.class); + return news; + } + + public List getNews(int count) + { + List news = getAllNews(); + return news.subList(0, Math.min(count, news.size())); } + /* + * Helpers + */ private T parseJson(String content, Class type) { return new Gson().fromJson(content, type); } - private List fetchList(String url, Class type) + private List fetchYamlList(String url, Class type) { String content = downloader.download(url); List result = null; if (content != null) - result = parse(content, type); + result = parseYaml(content, type); else result = new ArrayList<>(); return result; } - public List getRelatedDocuments(Addon addon, int count) + private List parseYaml(String content, Class type) { - List result = new ArrayList(); - - String tagString = addon.getTags(); - List tags = null; - if (tagString != null && !tagString.isEmpty()) - tags = Arrays.asList(tagString.split(",")); + List result = new ArrayList<>(); - if (tags != null) + if (content != null) { - for (String tag : tags) + for (String entry : content.trim().split("---")) { - tag = tag.trim(); - for (Document doc : getAllDocuments()) + if (!entry.trim().isEmpty()) { - if ((doc.getSummary() != null && doc.getSummary().contains(tag)) - || (doc.getSummary() != null && doc.getTitle().contains(tag))) - { - result.add(doc); - } + T obj = new Yaml().loadAs(entry, type); + result.add(obj); } } } - return new ArrayList(); + return result; } } diff --git a/src/main/java/org/jboss/forge/website/view/DocumentBean.java b/src/main/java/org/jboss/forge/website/view/DocumentBean.java index fc0adb1..0964b5d 100644 --- a/src/main/java/org/jboss/forge/website/view/DocumentBean.java +++ b/src/main/java/org/jboss/forge/website/view/DocumentBean.java @@ -88,6 +88,7 @@ public void retrieve() throws IOException if (documentTitle.equalsIgnoreCase(document.getTitle().replaceAll("-+", " ").replaceAll("\\s+", " "))) { this.document = document; + this.documentTitle = document.getTitle(); break; } } diff --git a/src/main/java/org/jboss/forge/website/view/IndexBean.java b/src/main/java/org/jboss/forge/website/view/IndexBean.java index f01048b..c31809a 100644 --- a/src/main/java/org/jboss/forge/website/view/IndexBean.java +++ b/src/main/java/org/jboss/forge/website/view/IndexBean.java @@ -14,6 +14,7 @@ import org.jboss.forge.website.model.Addon; import org.jboss.forge.website.model.Contributor; +import org.jboss.forge.website.model.News; import org.jboss.forge.website.service.RepositoryService; /** @@ -36,4 +37,9 @@ public List getContributors() { return service.getRandomContributors(5); } + + public List getNewsFeed() + { + return service.getNews(5); + } } diff --git a/src/main/java/org/jboss/forge/website/view/NewsBean.java b/src/main/java/org/jboss/forge/website/view/NewsBean.java new file mode 100644 index 0000000..6a56ad4 --- /dev/null +++ b/src/main/java/org/jboss/forge/website/view/NewsBean.java @@ -0,0 +1,154 @@ +package org.jboss.forge.website.view; + +import java.io.IOException; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.List; + +import javax.enterprise.context.ConversationScoped; +import javax.faces.context.FacesContext; +import javax.inject.Inject; +import javax.inject.Named; + +import org.jboss.forge.website.SiteConstants; +import org.jboss.forge.website.model.News; +import org.jboss.forge.website.service.Downloader; +import org.jboss.forge.website.service.RepositoryService; +import org.ocpsoft.common.util.Strings; +import org.ocpsoft.urlbuilder.Address; +import org.ocpsoft.urlbuilder.AddressBuilder; + +/** + * Backing bean for Document entities. + *

+ * This class provides CRUD functionality for all Document entities. It focuses purely on Java EE 6 standards (e.g. + * @ConversationScoped for state management, PersistenceContext for persistence, + * CriteriaBuilder for searches) rather than introducing a CRUD framework or custom base class. + */ + +@Named +@ConversationScoped +public class NewsBean implements Serializable +{ + private static final long serialVersionUID = -1447177331142569029L; + + @Inject + private transient Downloader downloader; + + @Inject + private RepositoryService service; + + private String documentTitle; + private News document; + + private List documents; + private String searchQuery; + + public void load() + { + List result = new ArrayList<>(); + List documents = service.getAllNews(); + + for (News document : documents) + { + if (Strings.isNullOrEmpty(searchQuery) + || + (document.getTitle() != null && document.getTitle().toLowerCase().contains(searchQuery.toLowerCase())) + || (document.getSummary() != null && document.getSummary().toLowerCase() + .contains(searchQuery.toLowerCase())) + || (document.getAuthor() != null && document.getAuthor().toLowerCase() + .contains(searchQuery.toLowerCase()))) + { + result.add(document); + } + + } + + this.setDocuments(result); + } + + public void retrieve() throws IOException + { + if (documentTitle != null) + { + for (News document : service.getAllNews()) + { + if (documentTitle.equalsIgnoreCase(document.getTitle().replaceAll("-+", " ").replaceAll("\\s+", " "))) + { + this.document = document; + this.documentTitle = document.getTitle(); + break; + } + } + } + + if (document == null) + { + FacesContext.getCurrentInstance().getExternalContext().dispatch("/404"); + } + } + + public String getSearchQuery() + { + return searchQuery; + } + + public void setSearchQuery(String searchQuery) + { + this.searchQuery = searchQuery; + } + + public List getDocuments() + { + return documents; + } + + public void setDocuments(List documents) + { + this.documents = documents; + } + + public String getDocumentHTML() throws MalformedURLException + { + String result = null; + + if (document != null) + { + Address address = AddressBuilder.begin().scheme("http").domain(SiteConstants.REDOCULOUS_DOMAIN) + .path("/api/v1/serve") + .query("repo", document.getRepo()) + .query("ref", document.getRef()) + .query("path", document.getPath()).build(); + + try + { + result = downloader.download(address.toString()); + } + catch (IllegalStateException e) + { + System.out.println("Failed to download document: " + address); + } + } + + if (Strings.isNullOrEmpty(result)) + result = "No Content"; + + return result; + } + + public News getDocument() + { + return this.document; + } + + public String getDocumentTitle() + { + return documentTitle; + } + + public void setDocumentTitle(String documentTitle) + { + this.documentTitle = documentTitle; + } +} \ No newline at end of file diff --git a/src/main/webapp/news-entry.xhtml b/src/main/webapp/news-entry.xhtml new file mode 100644 index 0000000..5d7d39f --- /dev/null +++ b/src/main/webapp/news-entry.xhtml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + +

+
+ JBoss Forge › + News + › +
+
+ +
+ +
+ + + + + +

Contribute to this news

+

+ #{newsBean.document.repo} +

+ +
+ + +
+
+ +
+
+ +
+ + \ No newline at end of file diff --git a/src/main/webapp/news.xhtml b/src/main/webapp/news.xhtml new file mode 100644 index 0000000..d96d147 --- /dev/null +++ b/src/main/webapp/news.xhtml @@ -0,0 +1,77 @@ + + + + + + + + + + +
+
+

JBoss Forge is fast and extensible. Learn more about what you can do with Forge.

+
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ + + +
+ + + +   + + + +
+
+
+
+ +
+

+ +

+
+ + + Read this → + +
+
+
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/src/main/webapp/resources/scaffold/mainTemplate.xhtml b/src/main/webapp/resources/scaffold/mainTemplate.xhtml index 66b404b..31598bb 100644 --- a/src/main/webapp/resources/scaffold/mainTemplate.xhtml +++ b/src/main/webapp/resources/scaffold/mainTemplate.xhtml @@ -65,11 +65,12 @@