Java tutorial
/* * Symphony - A modern community (forum/SNS/blog) platform written in Java. * Copyright (C) 2012-2018, b3log.org & hacpai.com * * 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, see <http://www.gnu.org/licenses/>. */ package org.b3log.symphony.service; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.b3log.latke.logging.Level; import org.b3log.latke.logging.Logger; import org.b3log.latke.service.annotation.Service; import org.b3log.symphony.model.Common; import org.b3log.symphony.util.Markdowns; import org.json.JSONObject; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Manual query service. * <p> * Sees <a href="https://github.com/tldr-pages/tldr">tldr</a> for more details. * </p> * * @author <a href="http://88250.b3log.org">Liang Ding</a> * @version 1.0.1.3, Apr 19, 2017 * @since 1.8.0 */ @Service public class ManQueryService { /** * Logger. */ private static final Logger LOGGER = Logger.getLogger(ManQueryService.class); /** * All command manuals. */ private static final List<JSONObject> CMD_MANS = new ArrayList<>(); /** * Whether tldr is enabled. */ public static boolean TLDR_ENABLED; static { new Thread(ManQueryService::init).start(); } /** * Initializes manuals. */ private static void init() { // http://stackoverflow.com/questions/585534/what-is-the-best-way-to-find-the-users-home-directory-in-java final String userHome = System.getProperty("user.home"); if (StringUtils.isBlank(userHome)) { return; } try { Thread.sleep(5 * 1000); final String tldrPagesPath = userHome + File.separator + "tldr" + File.separator + "pages" + File.separator; final Collection<File> mans = FileUtils.listFiles(new File(tldrPagesPath), new String[] { "md" }, true); for (final File manFile : mans) { InputStream is = null; try { is = new FileInputStream(manFile); final String md = IOUtils.toString(is, "UTF-8"); String html = Markdowns.toHTML(md); final JSONObject cmdMan = new JSONObject(); cmdMan.put(Common.MAN_CMD, StringUtils.substringBeforeLast(manFile.getName(), ".")); html = html.replace("\n", "").replace("\r", ""); cmdMan.put(Common.MAN_HTML, html); CMD_MANS.add(cmdMan); } catch (final Exception e) { LOGGER.log(Level.ERROR, "Loads man [" + manFile.getPath() + "] failed", e); } finally { IOUtils.closeQuietly(is); } } } catch (final Exception e) { return; } TLDR_ENABLED = !CMD_MANS.isEmpty(); Collections.sort(CMD_MANS, (o1, o2) -> { final String c1 = o1.optString(Common.MAN_CMD); final String c2 = o2.optString(Common.MAN_CMD); return c1.compareToIgnoreCase(c2); }); } /** * Gets manuals by the specified command prefix. * * @param cmdPrefix the specified comman prefix * @return a list of manuals, for example, <pre> * [ * { * "manCmd": "find", * "manHTML": "...." * }, .... * ] * </pre>, returns an empty list if not found */ public List<JSONObject> getMansByCmdPrefix(final String cmdPrefix) { final JSONObject toSearch = new JSONObject(); toSearch.put(Common.MAN_CMD, cmdPrefix); final int index = Collections.binarySearch(CMD_MANS, toSearch, (o1, o2) -> { String c1 = o1.optString(Common.MAN_CMD); final String c2 = o2.optString(Common.MAN_CMD); if (c1.length() < c2.length()) { return c1.compareToIgnoreCase(c2); } c1 = c1.substring(0, c2.length()); return c1.compareToIgnoreCase(c2); }); final List<JSONObject> ret = new ArrayList<>(); if (index < 0) { return ret; } int start = index; int end = index; while (start > -1 && CMD_MANS.get(start).optString(Common.MAN_CMD).startsWith(cmdPrefix.toLowerCase())) { start--; } start++; final int WINDOW_SIZE = 8; if (start < index - WINDOW_SIZE) { end = start + WINDOW_SIZE; } else { while (end < CMD_MANS.size() && end < index + 5 && CMD_MANS.get(end).optString(Common.MAN_CMD).startsWith(cmdPrefix.toLowerCase())) { end++; if (end >= start + WINDOW_SIZE) { break; } } } return CMD_MANS.subList(start, end); } }