/** * Copyright © 2014 Instituto Superior Técnico * * This file is part of FenixEdu CMS. * * FenixEdu CMS is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FenixEdu CMS 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with FenixEdu CMS. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.cms.domain; import static java.util.Optional.ofNullable; import static org.apache.tika.io.FilenameUtils.normalize; import static org.fenixedu.commons.i18n.LocalizedString.fromJson; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.fenixedu.bennu.core.groups.Group; import org.fenixedu.bennu.io.domain.GroupBasedFile; import org.fenixedu.bennu.io.servlets.FileDownloadServlet; import org.fenixedu.cms.domain.component.CMSComponent; import org.fenixedu.cms.domain.component.Component; import org.fenixedu.cms.domain.component.ComponentDescriptor; import org.fenixedu.cms.domain.component.ListCategoryPosts; import org.fenixedu.commons.i18n.LocalizedString; import org.joda.time.DateTime; import com.google.common.collect.Maps; import com.google.common.io.ByteStreams; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import pt.ist.fenixframework.Atomic; /** * Created by borgez-dsi on 24-06-2015. */ public class SiteImporter { private static final JsonParser PARSER = new JsonParser(); private final ZipFile zipFile; public SiteImporter(ZipFile zipFile) { this.zipFile = zipFile; } @Atomic(mode = Atomic.TxMode.WRITE) public Site importSite() { JsonObject siteJson = getSiteJson(); Map<String, JsonObject> pagesDir = readJsonDirectory("pages/"); Map<String, JsonObject> postsDir = readJsonDirectory("posts/"); Map<String, JsonObject> categoriesDir = readJsonDirectory("categories/"); Map<String, JsonObject> menusDir = readJsonDirectory("menus/"); Site site = new Site(fromJson(siteJson.get("name")), fromJson(siteJson.get("description"))); site.setSlug(siteJson.get("slug").getAsString()); site.setCanViewGroup(Group.parse(siteJson.get("canViewGroup").getAsString())); if (siteJson.has("themeType") && !siteJson.get("themeType").isJsonNull()) { site.setThemeType(siteJson.get("themeType").getAsString()); } site.setEmbedded(siteJson.get("embedded").getAsBoolean()); if (siteJson.has("analyticsCode") && !siteJson.get("analyticsCode").isJsonNull()) { site.setAnalyticsCode(siteJson.get("analyticsCode").getAsString()); } for (Map.Entry<String, JsonObject> entry : categoriesDir.entrySet()) { importCategory(site, entry.getKey(), entry.getValue()); } for (Map.Entry<String, JsonObject> entry : postsDir.entrySet()) { importPost(site, entry.getKey(), entry.getValue()); } for (Map.Entry<String, JsonObject> entry : pagesDir.entrySet()) { importPage(site, entry.getKey(), entry.getValue()); } for (Map.Entry<String, JsonObject> entry : menusDir.entrySet()) { importMenu(site, entry.getKey(), entry.getValue()); } if (siteJson.has("initialPage") && !siteJson.get("initialPage").isJsonNull()) { site.setInitialPage(site.pageForSlug(siteJson.get("initialPage").getAsString())); } site.updateMenuFunctionality(); return site; } private Page importPage(Site site, String pageSlug, JsonObject jsonObject) { return ofNullable(site.pageForSlug(pageSlug)).orElseGet(() -> { Page page = new Page(site, fromJson(jsonObject.get("name"))); page.setSlug(jsonObject.get("slug").getAsString()); page.setCanViewGroup(Group.parse(jsonObject.get("canViewGroup").getAsString())); if (jsonObject.has("templateType") && !jsonObject.get("templateType").isJsonNull()) { page.setTemplateType(jsonObject.get("templateType").getAsString()); } page.setPublished(jsonObject.get("published").getAsBoolean()); for (JsonElement el : jsonObject.get("components").getAsJsonArray()) { Component component = importComponent(el.getAsJsonObject()); if (component != null) { page.addComponents(component); } } return page; }); } private Component importComponent(JsonObject jsonObject) { Component component = null; try { ComponentDescriptor descriptor = Component.forType(jsonObject.get("type").getAsString()); if (descriptor != null && !descriptor.isStateless()) { component = descriptor.fromJson(jsonObject); } else { component = Component.forType((Class<? extends CMSComponent>) descriptor.getType()); } } catch (Exception e) { } return component; } private Menu importMenu(Site site, String menuSlug, JsonObject jsonObject) { return ofNullable(site.menuForSlug(menuSlug)).orElseGet(() -> { Menu menu = new Menu(site, fromJson(jsonObject.get("name"))); menu.setSlug(jsonObject.get("slug").getAsString()); for (JsonElement childrenEl : jsonObject.get("topLevelItems").getAsJsonArray()) { importMenuItem(site, menu, null, childrenEl.getAsJsonObject()); } return menu; }); } private MenuItem importMenuItem(Site site, Menu menu, MenuItem parent, JsonObject jsonObject) { MenuItem menuItem = new MenuItem(menu); menuItem.setName(fromJson(jsonObject.get("name"))); menuItem.setPosition(jsonObject.get("position").getAsInt()); menuItem.setFolder(jsonObject.get("isFolder").getAsBoolean()); if (jsonObject.has("top") && !jsonObject.get("top").isJsonNull() && menu != null) { menuItem.setTop(menu); } if (jsonObject.has("parent") && !jsonObject.get("parent").isJsonNull() && parent != null) { menuItem.setParent(parent); } if (jsonObject.has("page")) { menuItem.setPage(site.pageForSlug(jsonObject.get("page").getAsString())); } for (JsonElement childrenEl : jsonObject.get("children").getAsJsonArray()) { importMenuItem(site, menu, menuItem, childrenEl.getAsJsonObject()); } return menuItem; } private Post importPost(Site site, String postSlug, JsonObject jsonObject) { return ofNullable(site.postForSlug(postSlug)).orElseGet(() -> { Post post = new Post(site); LocalizedString body = fromJson(jsonObject.get("body")); LocalizedString excerpt = jsonObject.has("excerpt") ? fromJson(jsonObject.get("excerpt")) : null; post.setName(fromJson(jsonObject.get("name"))); post.setSlug(jsonObject.get("slug").getAsString()); post.setCanViewGroup(Group.parse(jsonObject.get("canViewGroup").getAsString())); post.setActive(jsonObject.get("active").getAsBoolean()); if (jsonObject.has("location") && jsonObject.get("location").isJsonObject()) { post.setLocation(fromJson(jsonObject.get("location"))); } if (jsonObject.has("metadata") && jsonObject.get("metadata").isJsonObject()) { post.setMetadata(PostMetadata.fromJson(jsonObject.get("metadata"))); } if (jsonObject.has("publicationBegin") && jsonObject.get("publicationBegin").isJsonPrimitive()) { post.setPublicationBegin(DateTime.parse(jsonObject.get("publicationBegin").getAsString())); } if (jsonObject.has("publicationEnd") && jsonObject.get("publicationEnd").isJsonPrimitive()) { post.setPublicationEnd(DateTime.parse(jsonObject.get("publicationEnd").getAsString())); } if (jsonObject.has("categories") && jsonObject.get("categories").isJsonArray()) { for (JsonElement catSlug : jsonObject.get("categories").getAsJsonArray()) { post.addCategories(site.categoryForSlug(catSlug.getAsString())); } } for (JsonElement postFileEl : jsonObject.get("files").getAsJsonArray()) { JsonObject postFileJson = postFileEl.getAsJsonObject(); GroupBasedFile file = new GroupBasedFile(postFileJson.get("displayName").getAsString(), postFileJson.get("fileName").getAsString(), readFile(postFileJson.get("file").getAsString()), Group.parse(postFileJson.get("viewGroup").getAsString())); new PostFile(post, file, postFileJson.get("isEmbedded").getAsBoolean(), postFileJson.get("index").getAsInt()); body = replace(body, postFileJson.get("url").getAsString(), FileDownloadServlet.getDownloadUrl(file)); excerpt = replace(excerpt, postFileJson.get("url").getAsString(), FileDownloadServlet.getDownloadUrl(file)); } post.setBodyAndExcerpt(body, excerpt); return post; }); } private LocalizedString replace(LocalizedString localized, String origContent, String newContent) { LocalizedString result = new LocalizedString(); for (Locale locale : localized.getLocales()) { result = result.with(locale, localized.getContent(locale).replace(origContent, newContent)); } return result; } private byte[] readFile(String fileId) { try { return ByteStreams.toByteArray(getZipFile().getInputStream(getZipFile().getEntry(normalize("files/" + fileId)))); } catch (IOException e) { return new byte[]{}; } } private Category importCategory(Site site, String categorySlug, JsonObject jsonObject) { Category category = site.getOrCreateCategoryForSlug(categorySlug, fromJson(jsonObject.get("name"))); for (JsonElement el : jsonObject.get("components").getAsJsonArray()) { Component component = importComponent(el.getAsJsonObject()); if (component != null && ListCategoryPosts.class.isInstance(component)) { category.addComponents((ListCategoryPosts) component); } } System.out.println("importCategory - result: " + category); return category; } private JsonObject getSiteJson() { return getZipEntries("site.json"); } private JsonObject getZipEntries(String fileName) { try { Reader reader = new InputStreamReader(getZipFile().getInputStream(getZipFile().getEntry(fileName))); JsonObject jsonObject = new JsonParser().parse(reader).getAsJsonObject(); reader.close(); return jsonObject; } catch (IOException e) { return new JsonObject(); } } private Map<String, JsonObject> readJsonDirectory(String dirName) { Map<String, JsonObject> directoryEntries = Maps.newHashMap(); Enumeration<? extends ZipEntry> zipEntries = getZipFile().entries(); while (zipEntries.hasMoreElements()) { ZipEntry entry = zipEntries.nextElement(); if (!entry.isDirectory() && entry.getName().startsWith(dirName) && entry.getName().endsWith(".json")) { try { JsonObject json = PARSER.parse(new InputStreamReader(getZipFile().getInputStream(entry))).getAsJsonObject(); String entryName = entry.getName().substring(dirName.length(), entry.getName().lastIndexOf(".json")); directoryEntries.put(entryName, json); } catch (IOException e) { } } } return directoryEntries; } public ZipFile getZipFile() { return zipFile; } }