org.fenixedu.cms.domain.SiteImporter.java Source code

Java tutorial

Introduction

Here is the source code for org.fenixedu.cms.domain.SiteImporter.java

Source

/**
 * Copyright  2014 Instituto Superior Tcnico
 *
 * 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;
    }
}