package org.smartly.packages.cms.impl.cms.endpoint;
import org.json.JSONArray;
import org.json.JSONObject;
import org.smartly.Smartly;
import org.smartly.commons.lang.CharEncoding;
import org.smartly.commons.logging.Level;
import org.smartly.commons.logging.Logger;
import org.smartly.commons.util.ClassLoaderUtils;
import org.smartly.commons.util.JsonWrapper;
import org.smartly.commons.util.PathUtils;
import org.smartly.commons.util.StringUtils;
import org.smartly.packages.cms.SmartlyHttpCms;
import org.smartly.packages.http.SmartlyHttp;
import java.io.IOException;
import java.net.URL;
import java.util.*;
/**
* CMS Manager.
* <p/>
* <p>
* Extend SmartlyCMS for your site CMS manager.
* </p>
* <p/>
* <p/>
* Register a CMS manager calling SmartlyHttp.registerCMSEndPoint(<code>cms-instance</code>)
* in "ready" method of your AbstractPackage implementation.
*/
public class CMSRouter {
public static final String CHARSET = CharEncoding.getDefault();
private static final String FILE_ON_CREATE = "on_create.script";
private static final String FILE_HEAD = "hhead.ly";
private static final String FILE_HEADER = "hheader.ly";
private static final String FILE_CONTENT = "hcontent.ly";
private static final String FILE_FOOTER = "hfooter.ly";
private static final String FILE_SCRIPT = "hscript.ly";
private static final String FILE_SCRIPT_DBG = "hscript_dbg.ly";
private static final String FILE_LABELS = "labels.json";
private final String _root;
private final Map<String, JSONObject> _sitemap;
private final Map<String, CMSEndPointPage> _pages;
private final Map<String, String> _templates;
private final List<CMSUrl> _urls;
private CMSEndPointRepository _repo;
private boolean _restful;
public CMSRouter() {
_restful = false;
_root = getRootFullPath(this.getClass());
_sitemap = new HashMap<String, JSONObject>();
_pages = new HashMap<String, CMSEndPointPage>();
_templates = new HashMap<String, String>();
_urls = new ArrayList<CMSUrl>();
_repo = new CMSEndPointRepository(_root);
final JSONObject sitemap = _repo.getJSONObject("sitemap.json");
if (null != sitemap && sitemap.length() > 0) {
this.init(sitemap);
}
this.logReport();
}
public boolean contains(final String path) {
if (!_restful) {
return _sitemap.containsKey(path);
} else {
return null != this.getUrl(path);
}
}
public CMSEndPointPage getPage(final String path) {
if (!_restful) {
return _pages.get(path);
} else {
final CMSUrl url = this.getUrl(path);
return null != url ? _pages.get(url.getPath()) : null;
}
}
public String getPageTemplate(final String path) {
final String key;
if (!_restful) {
key = path;
} else {
final CMSUrl url = this.getUrl(path);
key = null != url ? url.getPath() : "";
}
if (StringUtils.hasText(key)) {
final JSONObject page = _sitemap.get(key);
final String templateUrl = JsonWrapper.getString(page, "template");
return _templates.get(templateUrl);
}
return "";
}
public Map<String, String> getRestParams(final String path) {
if (!_restful) {
return null;
} else {
final CMSUrl url = this.getUrl(path);
return null != url ? url.getParams(path) : null;
}
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private Logger getLogger() {
return SmartlyHttpCms.getCMSLogger();
}
private void init(final JSONObject sitemap) {
final JSONArray pages = JsonWrapper.getArray(sitemap, "pages");
if (null != pages && pages.length() > 0) {
for (int i = 0; i < pages.length(); i++) {
final JSONObject page = pages.optJSONObject(i);
if (null != page) {
try {
// url
final String[] urls = StringUtils.split(JsonWrapper.getString(page, "url"), ",");
// page
final String path = JsonWrapper.getString(page, "path");
final CMSEndPointPage sp = this.createPage(path);
// template
final String templatePath = JsonWrapper.getString(page, "template");
final String tpl = this.readTemplate(templatePath);
// add urls
this.initSitemapAndPages(urls, page, sp);
// add template
_templates.put(templatePath, tpl);
} catch (Throwable t) {
this.getLogger().log(Level.SEVERE, null, t);
}
}
}
}
//-- add CMS endpoints to Http Module --//
SmartlyHttp.registerCMSPaths(_sitemap.keySet());
}
private void initSitemapAndPages(final String[] paths,
final JSONObject smPage,
final CMSEndPointPage epPage) {
// add urls
for (final String path : paths) {
final CMSUrl url = new CMSUrl(path);
if (!_urls.contains(url)) {
_urls.add(url);
}
if (url.hasParams()) {
_restful = true;
}
_sitemap.put(path, smPage);
_pages.put(path, epPage);
}
}
private CMSUrl getUrl(final String path) {
for (final CMSUrl url : _urls) {
if (url.match(path)) {
return url;
}
}
return null;
}
private String readTemplate(final String path) throws IOException {
return SmartlyHttp.readFile(path);
}
private CMSEndPointPage createPage(final String path) throws Exception {
final String on_create = _repo.getString(PathUtils.concat(path, FILE_ON_CREATE));
final String hhead = _repo.getString(PathUtils.concat(path, FILE_HEAD));
final String hheader = _repo.getString(PathUtils.concat(path, FILE_HEADER));
final String hcontent = _repo.getString(PathUtils.concat(path, FILE_CONTENT));
final String hfooter = _repo.getString(PathUtils.concat(path, FILE_FOOTER));
final String hscript = _repo.getString(PathUtils.concat(path, FILE_SCRIPT));
final String hscriptdbg = _repo.getString(PathUtils.concat(path, FILE_SCRIPT_DBG));
final JSONObject labels = _repo.getJSONObject(PathUtils.concat(path, FILE_LABELS));
final CMSEndPointPage result = new CMSEndPointPage(path);
result.setScriptOnCreate(on_create);
result.setHead(hhead);
result.setHeader(hheader);
result.setContent(hcontent);
result.setFooter(hfooter);
result.setScript(isDebug() ? (StringUtils.hasText(hscriptdbg) ? hscriptdbg : hscript) : hscript);
result.setLocalizations(labels);
return result;
}
private void logReport() {
final StringBuilder sb = new StringBuilder();
sb.append("------- CMS ---------\n\t");
sb.append("CMS Root: " + _root).append("\n\t");
sb.append("CMS Repository Size: " + (null != _repo ? _repo.size() : 0)).append("\n\t");
// sitemaps
sb.append("SITE MAP:\n\t");
final Set<String> keys = _sitemap.keySet();
for (final String key : keys) {
sb.append(key).append("\n\t");
}
if (_sitemap.size() != _pages.size()) {
sb.append("WARNING!! - Sitemap and Pages have different lengths. ");
sb.append("\n\t");
}
sb.append(_pages.size()).append(" pages and ").append(_sitemap.size()).append(" sitemap items");
sb.append("\n\t");
this.getLogger().info(sb.toString());
}
// --------------------------------------------------------------------
// S T A T I C
// --------------------------------------------------------------------
private static boolean isDebug() {
return Smartly.isDebugMode();
}
private static String getRootFullPath(final Class aclass) {
final URL url = ClassLoaderUtils.getResource(null, aclass, "");
final String path = null != url ? url.getPath() : "";
if (StringUtils.hasText(path) && path.indexOf(":/") > -1 && path.startsWith("/")) {
return path.substring(1);
}
return path;
}
}