Java tutorial
/* * WebTop Services is a Web Application framework developed by Sonicle S.r.l. * Copyright (C) 2014 Sonicle S.r.l. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY SONICLE, SONICLE DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * 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 Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Sonicle S.r.l. at email address sonicle@sonicle.com * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * Sonicle logo and Sonicle copyright notice. If the display of the logo is not * reasonably feasible for technical reasons, the Appropriate Legal Notices must * display the words "Copyright (C) 2014 Sonicle S.r.l.". */ package com.sonicle.webtop.core.versioning; import com.sonicle.commons.LangUtils; import com.sonicle.webtop.core.sdk.ServiceVersion; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.MessageFormat; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; /** * * @author malbinola */ public class Whatsnew { private final Pattern PATTER_LINE = Pattern.compile("^(\\$|%|@|\\*|!)(.*)"); private String resourceName = null; private ServiceVersion version = null; private String listMode = "none"; private boolean listItem = false; private boolean prettyPrint = false; private final HashMap<Pattern, String> patterns = new HashMap<>(); private final LinkedHashMap<String, String> htmls = new LinkedHashMap<>(); public Whatsnew(String resourceName, HashMap<String, String> variables) { this.resourceName = resourceName; // Converts variables into regex patterns for (String key : variables.keySet()) { patterns.put(Pattern.compile("\\{" + key + "\\}"), StringUtils.defaultString(variables.get(key))); } } private void update(ServiceVersion fromVersion, ServiceVersion toVersion) throws IOException { InputStream is = null; BufferedReader br = null; if (fromVersion == null) fromVersion = new ServiceVersion(); if ((version != null) && (fromVersion.compareTo(version) >= 0)) return; try { is = LangUtils.findClassLoader(getClass()).getResourceAsStream(resourceName); if (is == null) throw new ResourceNotFoundException(); br = new BufferedReader(new InputStreamReader(is)); readFile(br, fromVersion, toVersion); version = fromVersion; } finally { IOUtils.closeQuietly(br); IOUtils.closeQuietly(is); } } private void readFile(BufferedReader reader, ServiceVersion fromVersion, ServiceVersion toVersion) throws IOException { Matcher matcher = null; String line = null, marker = null, text = null; ServiceVersion lineVersion = null; StringBuilder sb = null; boolean skip = false; int lineNo = 0; while ((line = reader.readLine()) != null) { lineNo++; line = StringUtils.trim(line); matcher = PATTER_LINE.matcher(line); if (matcher.matches()) { marker = matcher.group(1); text = StringUtils.trim(matcher.group(2)); text = LangUtils.escapeHtmlAccentsAndSymbols(text); if (marker.equals("$")) { // Version marker // Closes previous version's section if (sb != null) { this.closeList(sb); //htmls.put(lineVersion.toString(), sb.toString()); htmls.put(lineVersion.toString(), replaceVariables(sb.toString())); sb = null; } lineVersion = new ServiceVersion(text); if (lineVersion.getValue() == null) throw new IOException(MessageFormat.format("Bad version [{0}] at line {1}", text, lineNo)); skip = htmls.containsKey(lineVersion.toString()); // Skip all versions already processed! if (skip) continue; if (lineVersion.compareTo(fromVersion) <= 0) break; // Skip all version sections below fromVersion (included) if (lineVersion.compareTo(toVersion) > 0) continue; // Skip all version sections after toVersion sb = new StringBuilder(); // Prepares a new version section } else { if (skip) continue; if (sb == null) continue; // An active builder is required! if (marker.equals("%")) { // Version title this.closeList(sb); sb.append(MessageFormat.format("<div class='wt-wntitle'>{0}</div>", text)); if (prettyPrint) sb.append("\n"); } else if (marker.equals("@")) { // Version sub-title this.closeList(sb); sb.append(MessageFormat.format("<div class='wt-wnsubtitle'>{0}</div>", text)); if (prettyPrint) sb.append("\n"); } else if (marker.equals("!")) { // Free text this.closeList(sb); sb.append(MessageFormat.format("<div class='wt-wnfreetext'>{0}</div>", text)); if (prettyPrint) sb.append("\n"); } else if (marker.equals("*")) { // Unordered list this.closeListItem(sb); this.openList(sb, "unordered"); this.openListItem(sb); sb.append(text); } else { // No special markers this.closeList(sb); sb.append(text); if (prettyPrint) sb.append("\n"); } } } else { if (skip) continue; if (sb == null) continue; // An active builder is required! sb.append(" "); // Inserts a space between lines sb.append(LangUtils.escapeHtmlAccentsAndSymbols(line)); } } // Closes last version's section if (sb != null) { this.closeList(sb); //htmls.put(lineVersion.toString(), sb.toString()); htmls.put(lineVersion.toString(), replaceVariables(sb.toString())); sb = null; } } private String replaceVariables(String html) { for (Pattern patt : patterns.keySet()) { html = patt.matcher(html).replaceAll(patterns.get(patt)); } return html; } private void openList(StringBuilder sb, String mode) { if (!listMode.equals(mode)) { if (mode.equals("unordered")) { sb.append("<div class='wt-wnlist'><ul>"); if (prettyPrint) sb.append("\n"); } listMode = mode; } } private void closeList(StringBuilder sb) { if (listItem) { sb.append("</li>"); listItem = false; } if (listMode.equals("unordered")) { sb.append("</ul></div>"); if (prettyPrint) sb.append("\n"); } listMode = "none"; } private void openListItem(StringBuilder sb) { listItem = true; sb.append("<li>"); if (prettyPrint) sb.append("\n"); } private void closeListItem(StringBuilder sb) { if (listItem) { sb.append("</li>"); listItem = false; } } public String toHtml(ServiceVersion fromVersion, ServiceVersion toVersion) throws IOException { update(fromVersion, toVersion); return buildHtml(fromVersion, toVersion); } private String buildHtml(ServiceVersion fromVersion, ServiceVersion toVersion) { if (fromVersion == null) fromVersion = new ServiceVersion(); StringBuilder sb = new StringBuilder(); ServiceVersion vers = null; for (String key : htmls.keySet()) { vers = new ServiceVersion(key); if (vers.compareTo(fromVersion) <= 0) break; // Skip all version sections below fromVersion (included) if (vers.compareTo(toVersion) > 0) break; // Skip all version sections after toVersion sb.append(htmls.get(key)); } return sb.toString(); } }