Java tutorial
/** * Licensed to the Sakai Foundation (SF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The SF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.sakaiproject.nakamura.files.migrator; import org.apache.commons.lang.StringUtils; import org.apache.sling.commons.json.JSONArray; import org.apache.sling.commons.json.JSONException; import org.apache.sling.commons.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Iterator; import java.util.Set; public class PageMigrator { private static final Logger LOGGER = LoggerFactory.getLogger(PageMigrator.class); private static final String EMPTY_DIV = "<div />"; private static final String[] imageExtensions = new String[] { ".jpg", ".jpeg", ".gif", ".png" }; private final DocMigrator docMigrator; public PageMigrator(DocMigrator docMigrator) { this.docMigrator = docMigrator; } protected JSONObject generateEmptyRow(int columnCount) throws JSONException { JSONObject row = new JSONObject(); row.put("id", generateWidgetId()); JSONArray columns = new JSONArray(); for (int i = 0; i < columnCount; i++) { JSONObject column = new JSONObject(); column.put("width", 1 / columnCount); column.put("elements", new JSONArray()); columns.put(column); } row.put("columns", columns); return row; } protected String generateWidgetId() { return "id" + Math.round(Math.random() * 10000000); } protected void ensureRowPresent(JSONObject page) throws JSONException { JSONArray rows = page.getJSONArray("rows"); if (rows == null || rows.length() < 1) { rows = new JSONArray(); rows.put(generateEmptyRow(1)); page.put("rows", rows); } } protected void generateNewCell(String id, String type, JSONObject page, JSONObject row, int column, JSONObject widgetData) throws JSONException { if (!"tooltip".equals(type) && !"joinrequestbuttons".equals(type)) { String columnId = id == null ? generateWidgetId() : id; JSONObject element = new JSONObject(); element.put("id", columnId); element.put("type", type); row.getJSONArray("columns").getJSONObject(column).accumulate("elements", element); if (widgetData != null) { page.put(columnId, widgetData); } } } protected JSONObject addRowToPage(JSONObject row, JSONObject page, int columnsForNextRow, Element htmlElement) throws JSONException { if (!isEmpty(htmlElement)) { generateNewCell(null, "htmlblock", page, row, 0, generateHtmlBlock(htmlElement.html())); } boolean rowHasContent = false; for (int i = 0; i < row.getJSONArray("columns").length(); i++) { if (row.getJSONArray("columns").getJSONObject(i).getJSONArray("elements").length() > 0) { rowHasContent = true; break; } } boolean rowAlreadyPresent = false; for (int i = 0; i < page.getJSONArray("rows").length(); i++) { if (row == page.getJSONArray("rows").getJSONObject(i)) { rowAlreadyPresent = true; break; } } if (rowHasContent && !rowAlreadyPresent) { page.accumulate("rows", row); } return generateEmptyRow(columnsForNextRow > 0 ? columnsForNextRow : 1); } protected JSONObject generateHtmlBlock(String html) throws JSONException { JSONObject contentObject = new JSONObject(); contentObject.put("content", html); JSONObject htmlBlockObject = new JSONObject(); htmlBlockObject.put("htmlblock", contentObject); return htmlBlockObject; } boolean isEmpty(Element htmlElement) { // filter out TinyMCE instances htmlElement.select(".mceEditor").remove(); String htmlContent = htmlElement.text().trim(); String[] elementNames = new String[] { "img", "iframe", "frame", "input", "select", "option" }; boolean containsElement = false; for (String elementName : elementNames) { if (!htmlElement.select(elementName).isEmpty()) { containsElement = true; } } return !(htmlElement.hasText() || containsElement); } void processPageReference(JSONObject subtree, JSONObject originalStructure, JSONObject newStructure, Set<String> widgetsUsed, String reference) throws JSONException { if (reference.startsWith("_")) { return; } JSONObject structureItem = subtree.getJSONObject(reference); if (!structureItem.has("_ref") || StringUtils.isBlank(structureItem.getString("_ref"))) { return; } LOGGER.debug("processing page {} from structure0", reference); String ref = structureItem.getString("_ref"); if (!originalStructure.has(ref) || !originalStructure.getJSONObject(ref).has("rows")) { newStructure.put(ref, migratePage(originalStructure, newStructure.getString("_path"), widgetsUsed, ref)); } docMigrator.processStructure0(structureItem, originalStructure, newStructure); } JSONObject migratePage(JSONObject originalStructure, String contentId, Set<String> widgetsUsed, String ref) throws JSONException { Document page; JSONObject oldFashionedWidget = originalStructure.getJSONObject(ref); if (oldFashionedWidget.has("page")) { page = Jsoup.parse(oldFashionedWidget.getString("page")); if (originalStructure.has("resources")) { LOGGER.debug("This may be an IMS-CP document. Looking for images..."); Elements images = page.select("img"); LOGGER.debug("Found {} images to process.", images.size()); for (Element image : images) { String imgSrc = image.attr("src"); LOGGER.debug("Looking at image path '{}'", imgSrc); if (imgSrc.startsWith("p/") && hasImageExtension(imgSrc)) { image.attr("src", imgSrc.substring(0, imgSrc.lastIndexOf(".") + 1)); } } } } else { page = Jsoup.parse(EMPTY_DIV); } Document currentHtmlBlock = Jsoup.parse(EMPTY_DIV); JSONObject currentPage = new JSONObject(); currentPage.put("rows", new JSONArray()); JSONObject currentRow = generateEmptyRow(1); Elements topLevelElements = page.select("body").first().children(); for (Element topLevelElement : topLevelElements) { if (topLevelElement.select(".widget_inline").size() > 0) { addRowToPage(currentRow, currentPage, 0, currentHtmlBlock.select("body").first()); currentHtmlBlock = Jsoup.parse(EMPTY_DIV); int numColumns = 1; int leftSideColumn = topLevelElement.select(".widget_inline.block_image_left").size() > 0 ? 1 : 0; numColumns += leftSideColumn; int rightSideColumn = topLevelElement.select(".widget_inline.block_image_right").size() > 0 ? 1 : 0; numColumns += rightSideColumn; if (numColumns > 1) { currentRow = addRowToPage(currentRow, currentPage, numColumns, currentHtmlBlock.select("body").first()); } for (Element widgetElement : topLevelElement.select(".widget_inline")) { extractWidget(originalStructure, contentId, widgetsUsed, ref, currentPage, currentRow, leftSideColumn, widgetElement); } if (numColumns > 1) { currentRow = addRowToPage(currentRow, currentPage, 1, currentHtmlBlock.select("body").first()); } } else { currentHtmlBlock.select("div").first().appendChild(topLevelElement); } } addRowToPage(currentRow, currentPage, 1, currentHtmlBlock.select("body").first()); ensureRowPresent(currentPage); return currentPage; } private boolean hasImageExtension(String imgSrc) { boolean hasImageExtension = false; for (String extension : imageExtensions) { if (imgSrc.endsWith(extension)) { hasImageExtension = true; break; } } return hasImageExtension; } void extractWidget(JSONObject originalStructure, String contentId, Set<String> widgetsUsed, String ref, JSONObject currentPage, JSONObject currentRow, int leftSideColumn, Element widgetElement) throws JSONException { String[] widgetIdParts = widgetElement.attr("id").split("_"); String widgetType = widgetIdParts[1]; String widgetId = widgetIdParts.length > 2 ? widgetIdParts[2] : generateWidgetId(); int columnIndex; if (widgetElement.hasClass("block_image_left")) { columnIndex = 0; } else if (widgetElement.hasClass("block_image_right")) { columnIndex = leftSideColumn > 0 ? 2 : 1; } else { columnIndex = leftSideColumn > 0 ? 1 : 0; } generateNewCell(widgetId, widgetType, currentPage, currentRow, columnIndex, getJSONObjectOrNull(originalStructure, widgetId)); widgetsUsed.add(widgetId); if ("discussion".equals(widgetType)) { migrateDiscussionWidget(contentId, ref, currentPage, widgetId); } widgetElement.remove(); } void migrateDiscussionWidget(String contentId, String ref, JSONObject currentPage, String widgetId) throws JSONException { String newMessageStorePath = contentId + "/" + ref + "/" + widgetId + "/discussion/message"; String newAbsoluteMessageStorePath = "/p/" + newMessageStorePath; JSONObject inbox = currentPage.getJSONObject(widgetId).getJSONObject("discussion").getJSONObject("message") .getJSONObject("inbox"); for (Iterator<String> inboxIterator = inbox.keys(); inboxIterator.hasNext();) { String inboxKey = inboxIterator.next(); if (inboxKey.startsWith("_")) { continue; } inbox.getJSONObject(inboxKey).put("sakai:to", newAbsoluteMessageStorePath); inbox.getJSONObject(inboxKey).put("sakai:writeto", newAbsoluteMessageStorePath); inbox.getJSONObject(inboxKey).put("sakai:messagestore", newMessageStorePath + "/"); } } protected JSONObject getJSONObjectOrNull(JSONObject jsonObject, String key) throws JSONException { if (jsonObject.has(key)) { return jsonObject.getJSONObject(key); } else { return null; } } }