/*
* (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library 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.
*
* Contributors:
* Anahide Tchertchian
*/
package org.nuxeo.ecm.platform.forms.layout.io;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.platform.forms.layout.api.FieldDefinition;
import org.nuxeo.ecm.platform.forms.layout.api.LayoutDefinition;
import org.nuxeo.ecm.platform.forms.layout.api.LayoutRowDefinition;
import org.nuxeo.ecm.platform.forms.layout.api.LayoutTypeConfiguration;
import org.nuxeo.ecm.platform.forms.layout.api.LayoutTypeDefinition;
import org.nuxeo.ecm.platform.forms.layout.api.RenderingInfo;
import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition;
import org.nuxeo.ecm.platform.forms.layout.api.WidgetReference;
import org.nuxeo.ecm.platform.forms.layout.api.WidgetSelectOption;
import org.nuxeo.ecm.platform.forms.layout.api.WidgetSelectOptions;
import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeConfiguration;
import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeDefinition;
import org.nuxeo.ecm.platform.forms.layout.api.converters.LayoutConversionContext;
import org.nuxeo.ecm.platform.forms.layout.api.converters.WidgetDefinitionConverter;
import org.nuxeo.ecm.platform.forms.layout.api.impl.FieldDefinitionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutDefinitionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutRowDefinitionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutTypeConfigurationImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutTypeDefinitionComparator;
import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutTypeDefinitionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.RenderingInfoImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetDefinitionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetReferenceImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetSelectOptionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetSelectOptionsImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeConfigurationImpl;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeDefinitionComparator;
import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeDefinitionImpl;
import org.nuxeo.ecm.platform.forms.layout.api.service.LayoutStore;
import org.nuxeo.runtime.api.Framework;
/**
* JSON exporter for layout objects
*
* @author Anahide Tchertchian
* @since 5.4.2
*/
public class JSONLayoutExporter {
private static final Log log = LogFactory.getLog(JSONLayoutExporter.class);
public static final String ENCODED_VALUES_ENCODING = "UTF-8";
public static String encode(JSONObject jsonObject)
throws UnsupportedEncodingException {
String json = jsonObject.toString();
String encodedValues = Base64.encodeBytes(json.getBytes(), Base64.GZIP
| Base64.DONT_BREAK_LINES);
return URLEncoder.encode(encodedValues, ENCODED_VALUES_ENCODING);
}
public static JSONObject decode(String json)
throws UnsupportedEncodingException {
String decodedValues = URLDecoder.decode(json, ENCODED_VALUES_ENCODING);
json = new String(Base64.decode(decodedValues));
return JSONObject.fromObject(json);
}
/**
* @since 5.5
* @throws IOException
*/
public static void export(String category, LayoutDefinition layoutDef,
LayoutConversionContext ctx,
List<WidgetDefinitionConverter> widgetConverters, OutputStream out)
throws IOException {
JSONObject res = exportToJson(category, layoutDef, ctx,
widgetConverters);
out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING));
}
public static void export(WidgetTypeDefinition def, OutputStream out)
throws IOException {
JSONObject res = exportToJson(def);
out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING));
}
public static void export(List<WidgetTypeDefinition> defs, OutputStream out)
throws IOException {
JSONObject res = new JSONObject();
if (defs != null) {
// sort so that order is deterministic
Collections.sort(defs, new WidgetTypeDefinitionComparator(false));
}
for (WidgetTypeDefinition def : defs) {
res.element(def.getName(), exportToJson(def));
}
out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING));
}
/**
* @since 6.0
*/
public static void exportLayoutType(LayoutTypeDefinition def,
OutputStream out) throws IOException {
JSONObject res = exportToJson(def);
out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING));
}
/**
* @since 6.0
*/
public static void exportLayoutTypes(List<LayoutTypeDefinition> defs,
OutputStream out) throws IOException {
JSONObject res = new JSONObject();
if (defs != null) {
// sort so that order is deterministic
Collections.sort(defs, new LayoutTypeDefinitionComparator());
}
for (LayoutTypeDefinition def : defs) {
res.element(def.getName(), exportToJson(def));
}
out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING));
}
public static JSONObject exportToJson(WidgetTypeDefinition def) {
JSONObject json = new JSONObject();
json.element("name", def.getName());
List<String> caliases = def.getAliases();
if (caliases != null && !caliases.isEmpty()) {
JSONArray aliases = new JSONArray();
for (String alias : caliases) {
aliases.add(alias);
}
json.element("aliases", aliases);
}
json.element("handlerClassName", def.getHandlerClassName());
JSONObject props = exportStringPropsToJson(def.getProperties());
if (!props.isEmpty()) {
json.element("properties", props);
}
WidgetTypeConfiguration conf = def.getConfiguration();
if (conf != null) {
json.element("configuration", exportToJson(conf));
}
return json;
}
@SuppressWarnings("unchecked")
public static WidgetTypeDefinition importWidgetTypeDefinition(
JSONObject jsonDef) {
String name = jsonDef.optString("name");
String handlerClass = jsonDef.optString("handlerClassName");
Map<String, String> properties = importStringProps(jsonDef.optJSONObject("properties"));
WidgetTypeConfiguration conf = importWidgetTypeConfiguration(jsonDef.optJSONObject("configuration"));
List<String> aliases = new ArrayList<String>();
JSONArray jaliases = jsonDef.optJSONArray("aliases");
if (jaliases != null) {
aliases.addAll(jaliases);
}
WidgetTypeDefinitionImpl res = new WidgetTypeDefinitionImpl(name,
handlerClass, properties, conf);
res.setAliases(aliases);
return res;
}
public static JSONObject exportToJson(WidgetTypeConfiguration conf) {
JSONObject json = new JSONObject();
json.element("title", conf.getTitle());
json.element("description", conf.getDescription());
String demoId = conf.getDemoId();
if (demoId != null) {
JSONObject demoInfo = new JSONObject();
demoInfo.element("id", demoId);
demoInfo.element("previewEnabled", conf.isDemoPreviewEnabled());
json.element("demo", demoInfo);
}
json.element("sinceVersion", conf.getSinceVersion());
String deprVersion = conf.getDeprecatedVersion();
if (!StringUtils.isBlank(deprVersion)) {
json.element("deprecatedVersion", deprVersion);
}
JSONObject confProps = exportPropsToJson(conf.getConfProperties());
if (!confProps.isEmpty()) {
json.element("confProperties", confProps);
}
JSONArray supportedModes = new JSONArray();
List<String> confSupportedModes = conf.getSupportedModes();
if (confSupportedModes != null) {
supportedModes.addAll(confSupportedModes);
}
if (!supportedModes.isEmpty()) {
json.element("supportedModes", supportedModes);
}
if (conf.isAcceptingSubWidgets()) {
json.element("acceptingSubWidgets", conf.isAcceptingSubWidgets());
}
if (conf.isHandlingLabels()) {
json.element("handlingLabels", conf.isHandlingLabels());
}
JSONArray supportedControls = new JSONArray();
List<String> confSupportedControls = conf.getSupportedControls();
if (confSupportedControls != null) {
supportedControls.addAll(confSupportedControls);
}
if (!supportedControls.isEmpty()) {
json.element("supportedControls", supportedControls);
}
if (conf.isContainingForm()) {
json.element("containingForm", true);
}
JSONObject fields = new JSONObject();
fields.element("list", conf.isList());
fields.element("complex", conf.isComplex());
JSONArray supportedTypes = new JSONArray();
List<String> confSupportedTypes = conf.getSupportedFieldTypes();
if (confSupportedTypes != null) {
supportedTypes.addAll(confSupportedTypes);
}
if (!supportedTypes.isEmpty()) {
fields.element("supportedTypes", supportedTypes);
}
JSONArray defaultTypes = new JSONArray();
List<String> confDefaultTypes = conf.getDefaultFieldTypes();
if (confDefaultTypes != null) {
defaultTypes.addAll(confDefaultTypes);
}
if (!defaultTypes.isEmpty()) {
fields.element("defaultTypes", defaultTypes);
}
JSONArray defaultFieldDefs = new JSONArray();
List<FieldDefinition> fieldDefs = conf.getDefaultFieldDefinitions();
if (fieldDefs != null) {
for (FieldDefinition fieldDef : fieldDefs) {
defaultFieldDefs.add(exportToJson(fieldDef));
}
}
if (!defaultFieldDefs.isEmpty()) {
fields.element("defaultConfiguration", defaultFieldDefs);
}
Map<String, List<LayoutDefinition>> fieldLayouts = conf.getFieldLayouts();
if (fieldLayouts != null) {
List<String> modes = new ArrayList<String>(fieldLayouts.keySet());
// sort so that order is deterministic
Collections.sort(modes);
JSONObject layouts = new JSONObject();
for (String mode : modes) {
JSONArray modeLayouts = new JSONArray();
for (LayoutDefinition layoutDef : fieldLayouts.get(mode)) {
modeLayouts.add(exportToJson(null, layoutDef));
}
layouts.element(mode, modeLayouts);
}
if (!layouts.isEmpty()) {
fields.element("layouts", layouts);
}
}
json.element("fields", fields);
JSONArray cats = new JSONArray();
List<String> confCats = conf.getCategories();
if (confCats != null) {
cats.addAll(confCats);
}
if (!cats.isEmpty()) {
json.element("categories", cats);
}
JSONObject props = new JSONObject();
Map<String, List<LayoutDefinition>> confLayouts = conf.getPropertyLayouts();
if (confLayouts != null) {
List<String> modes = new ArrayList<String>(confLayouts.keySet());
// sort so that order is deterministic
Collections.sort(modes);
JSONObject layouts = new JSONObject();
for (String mode : modes) {
JSONArray modeLayouts = new JSONArray();
for (LayoutDefinition layoutDef : confLayouts.get(mode)) {
modeLayouts.add(exportToJson(null, layoutDef));
}
layouts.element(mode, modeLayouts);
}
if (!layouts.isEmpty()) {
props.element("layouts", layouts);
}
}
Map<String, Map<String, Serializable>> defaultPropValues = conf.getDefaultPropertyValues();
if (defaultPropValues != null && !defaultPropValues.isEmpty()) {
json.element("defaultPropertyValues",
exportPropsByModeToJson(defaultPropValues));
}
if (!props.isEmpty()) {
json.element("properties", props);
}
Map<String, Map<String, Serializable>> defaultControlValues = conf.getDefaultControlValues();
if (defaultControlValues != null && !defaultControlValues.isEmpty()) {
json.element("defaultControlValues",
exportPropsByModeToJson(defaultControlValues));
}
return json;
}
@SuppressWarnings("unchecked")
public static WidgetTypeConfiguration importWidgetTypeConfiguration(
JSONObject conf) {
WidgetTypeConfigurationImpl res = new WidgetTypeConfigurationImpl();
if (conf == null) {
return res;
}
res.setTitle(conf.getString("title"));
res.setDescription(conf.optString("description"));
res.setSinceVersion(conf.optString("sinceVersion"));
res.setDeprecatedVersion(conf.optString("deprecatedVersion"));
JSONObject demoInfo = conf.optJSONObject("demo");
String demoId = null;
boolean demoPreviewEnabled = false;
if (demoInfo != null && !demoInfo.isNullObject()) {
demoId = demoInfo.optString("id");
demoPreviewEnabled = demoInfo.optBoolean("previewEnabled");
}
res.setDemoId(demoId);
res.setDemoPreviewEnabled(demoPreviewEnabled);
res.setProperties(importProps(conf.optJSONObject("confProperties")));
List<String> confSupportedModes = new ArrayList<String>();
JSONArray supportedModes = conf.optJSONArray("supportedModes");
if (supportedModes != null) {
confSupportedModes.addAll(supportedModes);
}
res.setSupportedModes(confSupportedModes);
res.setAcceptingSubWidgets(conf.optBoolean("acceptingSubWidgets", false));
res.setHandlingLabels(conf.optBoolean("handlingLabels", false));
List<String> confSupportedControls = new ArrayList<String>();
JSONArray supportedControls = conf.optJSONArray("supportedControls");
if (supportedControls != null) {
confSupportedControls.addAll(supportedControls);
}
res.setSupportedControls(confSupportedControls);
res.setContainingForm(conf.optBoolean("containingForm", false));
JSONObject fields = conf.optJSONObject("fields");
boolean list = false;
boolean complex = false;
List<String> confSupportedTypes = new ArrayList<String>();
List<String> confDefaultTypes = new ArrayList<String>();
List<FieldDefinition> defaultFieldDefinitions = new ArrayList<FieldDefinition>();
Map<String, List<LayoutDefinition>> fieldLayouts = new HashMap<String, List<LayoutDefinition>>();
if (fields != null && !fields.isNullObject()) {
list = fields.optBoolean("list", false);
complex = fields.optBoolean("complex", false);
JSONArray supportedTypes = fields.optJSONArray("supportedTypes");
if (supportedTypes != null) {
confSupportedTypes.addAll(supportedTypes);
}
JSONArray defaultTypes = fields.optJSONArray("defaultTypes");
if (defaultTypes != null) {
confDefaultTypes.addAll(defaultTypes);
}
JSONArray jfields = fields.optJSONArray("defaultConfiguration");
if (jfields != null) {
for (Object item : jfields) {
defaultFieldDefinitions.add(importFieldDefinition((JSONObject) item));
}
}
JSONObject layouts = fields.optJSONObject("layouts");
if (layouts != null && !layouts.isNullObject()) {
for (Object item : layouts.keySet()) {
String mode = (String) item;
List<LayoutDefinition> layoutDefs = new ArrayList<LayoutDefinition>();
JSONArray modeLayouts = layouts.getJSONArray(mode);
if (modeLayouts != null && !mode.isEmpty()) {
for (Object subitem : modeLayouts) {
layoutDefs.add(importLayoutDefinition((JSONObject) subitem));
}
}
fieldLayouts.put(mode, layoutDefs);
}
}
}
res.setList(list);
res.setComplex(complex);
res.setSupportedFieldTypes(confSupportedTypes);
res.setDefaultFieldTypes(confDefaultTypes);
res.setDefaultFieldDefinitions(defaultFieldDefinitions);
res.setFieldLayouts(fieldLayouts);
JSONArray cats = conf.optJSONArray("categories");
List<String> confCats = new ArrayList<String>();
if (cats != null) {
confCats.addAll(cats);
}
res.setCategories(confCats);
JSONObject props = conf.optJSONObject("properties");
Map<String, List<LayoutDefinition>> confLayouts = new HashMap<String, List<LayoutDefinition>>();
if (props != null && !props.isNullObject()) {
JSONObject layouts = props.optJSONObject("layouts");
if (layouts != null && !layouts.isNullObject()) {
for (Object item : layouts.keySet()) {
String mode = (String) item;
List<LayoutDefinition> layoutDefs = new ArrayList<LayoutDefinition>();
JSONArray modeLayouts = layouts.getJSONArray(mode);
if (modeLayouts != null && !mode.isEmpty()) {
for (Object subitem : modeLayouts) {
layoutDefs.add(importLayoutDefinition((JSONObject) subitem));
}
}
confLayouts.put(mode, layoutDefs);
}
}
}
res.setPropertyLayouts(confLayouts);
JSONObject defaultPropertyValues = conf.optJSONObject("defaultPropertyValues");
Map<String, Map<String, Serializable>> confDefaultProps = importPropsByMode(defaultPropertyValues);
res.setDefaultPropertyValues(confDefaultProps);
JSONObject defaultControlValues = conf.optJSONObject("defaultControlValues");
Map<String, Map<String, Serializable>> confDefaultControls = importPropsByMode(defaultControlValues);
res.setDefaultControlValues(confDefaultControls);
return res;
}
/**
* @since 6.0
*/
public static JSONObject exportToJson(LayoutTypeDefinition def) {
JSONObject json = new JSONObject();
json.element("name", def.getName());
List<String> caliases = def.getAliases();
if (caliases != null && !caliases.isEmpty()) {
JSONArray aliases = new JSONArray();
for (String alias : caliases) {
aliases.add(alias);
}
json.element("aliases", aliases);
}
JSONObject templates = exportStringPropsToJson(def.getTemplates());
if (!templates.isEmpty()) {
json.element("templates", templates);
}
LayoutTypeConfiguration conf = def.getConfiguration();
if (conf != null) {
json.element("configuration", exportToJson(conf));
}
return json;
}
/**
* @since 6.0
*/
@SuppressWarnings("unchecked")
public static LayoutTypeDefinition importLayoutTypeDefinition(
JSONObject jsonDef) {
String name = jsonDef.optString("name");
Map<String, String> templates = importStringProps(jsonDef.optJSONObject("templates"));
LayoutTypeConfiguration conf = importLayoutTypeConfiguration(jsonDef.optJSONObject("configuration"));
List<String> aliases = new ArrayList<String>();
JSONArray jaliases = jsonDef.optJSONArray("aliases");
if (jaliases != null) {
aliases.addAll(jaliases);
}
LayoutTypeDefinitionImpl res = new LayoutTypeDefinitionImpl(name,
templates, conf);
res.setAliases(aliases);
return res;
}
/**
* @since 6.0
*/
public static JSONObject exportToJson(LayoutTypeConfiguration conf) {
JSONObject json = new JSONObject();
json.element("title", conf.getTitle());
json.element("description", conf.getDescription());
String demoId = conf.getDemoId();
if (demoId != null) {
JSONObject demoInfo = new JSONObject();
demoInfo.element("id", demoId);
demoInfo.element("previewEnabled", conf.isDemoPreviewEnabled());
json.element("demo", demoInfo);
}
json.element("sinceVersion", conf.getSinceVersion());
String deprVersion = conf.getDeprecatedVersion();
if (!StringUtils.isBlank(deprVersion)) {
json.element("deprecatedVersion", deprVersion);
}
JSONArray supportedModes = new JSONArray();
List<String> confSupportedModes = conf.getSupportedModes();
if (confSupportedModes != null) {
supportedModes.addAll(confSupportedModes);
}
if (!supportedModes.isEmpty()) {
json.element("supportedModes", supportedModes);
}
if (conf.isHandlingLabels()) {
json.element("handlingLabels", conf.isHandlingLabels());
}
JSONArray supportedControls = new JSONArray();
List<String> confSupportedControls = conf.getSupportedControls();
if (confSupportedControls != null) {
supportedControls.addAll(confSupportedControls);
}
if (!supportedControls.isEmpty()) {
json.element("supportedControls", supportedControls);
}
if (conf.isContainingForm()) {
json.element("containingForm", true);
}
JSONArray cats = new JSONArray();
List<String> confCats = conf.getCategories();
if (confCats != null) {
cats.addAll(confCats);
}
if (!cats.isEmpty()) {
json.element("categories", cats);
}
JSONObject props = new JSONObject();
Map<String, List<LayoutDefinition>> confLayouts = conf.getPropertyLayouts();
if (confLayouts != null) {
List<String> modes = new ArrayList<String>(confLayouts.keySet());
// sort so that order is deterministic
Collections.sort(modes);
JSONObject layouts = new JSONObject();
for (String mode : modes) {
JSONArray modeLayouts = new JSONArray();
for (LayoutDefinition layoutDef : confLayouts.get(mode)) {
modeLayouts.add(exportToJson(null, layoutDef));
}
layouts.element(mode, modeLayouts);
}
if (!layouts.isEmpty()) {
props.element("layouts", layouts);
}
}
Map<String, Map<String, Serializable>> defaultPropValues = conf.getDefaultPropertyValues();
if (defaultPropValues != null && !defaultPropValues.isEmpty()) {
json.element("defaultPropertyValues",
exportPropsByModeToJson(defaultPropValues));
}
if (!props.isEmpty()) {
json.element("properties", props);
}
return json;
}
/**
* @since 6.0
*/
@SuppressWarnings("unchecked")
public static LayoutTypeConfiguration importLayoutTypeConfiguration(
JSONObject conf) {
LayoutTypeConfigurationImpl res = new LayoutTypeConfigurationImpl();
if (conf == null) {
return res;
}
res.setTitle(conf.getString("title"));
res.setDescription(conf.optString("description"));
res.setSinceVersion(conf.optString("sinceVersion"));
res.setDeprecatedVersion(conf.optString("deprecatedVersion"));
JSONObject demoInfo = conf.optJSONObject("demo");
String demoId = null;
boolean demoPreviewEnabled = false;
if (demoInfo != null && !demoInfo.isNullObject()) {
demoId = demoInfo.optString("id");
demoPreviewEnabled = demoInfo.optBoolean("previewEnabled");
}
res.setDemoId(demoId);
res.setDemoPreviewEnabled(demoPreviewEnabled);
List<String> confSupportedModes = new ArrayList<String>();
JSONArray supportedModes = conf.optJSONArray("supportedModes");
if (supportedModes != null) {
confSupportedModes.addAll(supportedModes);
}
res.setSupportedModes(confSupportedModes);
res.setHandlingLabels(conf.optBoolean("handlingLabels", false));
List<String> confSupportedControls = new ArrayList<String>();
JSONArray supportedControls = conf.optJSONArray("supportedControls");
if (supportedControls != null) {
confSupportedControls.addAll(supportedControls);
}
res.setSupportedControls(confSupportedControls);
res.setContainingForm(conf.optBoolean("containingForm", false));
JSONArray cats = conf.optJSONArray("categories");
List<String> confCats = new ArrayList<String>();
if (cats != null) {
confCats.addAll(cats);
}
res.setCategories(confCats);
JSONObject props = conf.optJSONObject("properties");
Map<String, List<LayoutDefinition>> confLayouts = new HashMap<String, List<LayoutDefinition>>();
if (props != null && !props.isNullObject()) {
JSONObject layouts = props.optJSONObject("layouts");
if (layouts != null && !layouts.isNullObject()) {
for (Object item : layouts.keySet()) {
String mode = (String) item;
List<LayoutDefinition> layoutDefs = new ArrayList<LayoutDefinition>();
JSONArray modeLayouts = layouts.getJSONArray(mode);
if (modeLayouts != null && !mode.isEmpty()) {
for (Object subitem : modeLayouts) {
layoutDefs.add(importLayoutDefinition((JSONObject) subitem));
}
}
confLayouts.put(mode, layoutDefs);
}
}
}
res.setPropertyLayouts(confLayouts);
JSONObject defaultPropertyValues = conf.optJSONObject("defaultPropertyValues");
Map<String, Map<String, Serializable>> confDefaultProps = importPropsByMode(defaultPropertyValues);
res.setDefaultPropertyValues(confDefaultProps);
return res;
}
public static JSONObject exportToJson(String category,
LayoutDefinition layoutDef) {
return exportToJson(category, layoutDef, null, null);
}
/**
* Returns the JSON export of this layout definition
*
* @since 5.5
* @param category the category of the layout, needed for retrieval of
* referenced global widgets.
* @param layoutDef the layout definition
* @param ctx the widget conversion context
* @param widgetConverters the list of ordered widget converters to use
* before export
* @return
*/
public static JSONObject exportToJson(String category,
LayoutDefinition layoutDef, LayoutConversionContext ctx,
List<WidgetDefinitionConverter> widgetConverters) {
JSONObject json = new JSONObject();
json.element("name", layoutDef.getName());
String type = layoutDef.getType();
if (type != null) {
json.element("type", type);
}
String typeCat = layoutDef.getTypeCategory();
if (typeCat != null) {
json.element("typeCategory", typeCat);
}
JSONObject templates = exportStringPropsToJson(layoutDef.getTemplates());
if (!templates.isEmpty()) {
json.element("templates", templates);
}
JSONObject props = exportPropsByModeToJson(layoutDef.getProperties());
if (!props.isEmpty()) {
json.element("properties", props);
}
JSONArray rows = new JSONArray();
LayoutRowDefinition[] defRows = layoutDef.getRows();
List<WidgetReference> widgetsToExport = new ArrayList<WidgetReference>();
if (defRows != null) {
int rowIndex = -1;
for (LayoutRowDefinition layoutRowDef : defRows) {
rowIndex++;
rows.add(exportToJson(layoutRowDef,
layoutRowDef.getDefaultName(rowIndex)));
WidgetReference[] widgets = layoutRowDef.getWidgetReferences();
if (widgets != null) {
for (WidgetReference widget : widgets) {
widgetsToExport.add(widget);
}
}
}
}
if (!rows.isEmpty()) {
json.element("rows", rows);
}
LayoutStore webLayoutManager = Framework.getLocalService(LayoutStore.class);
JSONArray widgets = new JSONArray();
for (WidgetReference widgetRef : widgetsToExport) {
WidgetDefinition widgetDef = exportWidgetReference(widgetRef,
category, layoutDef, ctx, webLayoutManager,
widgetConverters);
if (widgetDef != null) {
widgets.add(exportToJson(widgetDef, ctx, widgetConverters));
// also export local subwidgets references
WidgetReference[] subwidgetRefs = widgetDef.getSubWidgetReferences();
if (subwidgetRefs != null) {
for (WidgetReference subwidgetRef : subwidgetRefs) {
WidgetDefinition subwidgetDef = exportWidgetReference(
subwidgetRef, category, layoutDef, ctx,
webLayoutManager, widgetConverters);
if (subwidgetDef != null) {
widgets.add(exportToJson(subwidgetDef, ctx,
widgetConverters));
}
}
}
}
}
if (!widgets.isEmpty()) {
json.element("widgets", widgets);
}
JSONObject renderingInfos = exportRenderingInfosByModeToJson(layoutDef.getRenderingInfos());
if (!renderingInfos.isEmpty()) {
json.element("renderingInfos", renderingInfos);
}
List<String> caliases = layoutDef.getAliases();
if (caliases != null && !caliases.isEmpty()) {
JSONArray aliases = new JSONArray();
for (String alias : caliases) {
aliases.add(alias);
}
json.element("aliases", aliases);
}
return json;
}
protected static WidgetDefinition exportWidgetReference(
WidgetReference widgetRef, String category,
LayoutDefinition layoutDef, LayoutConversionContext ctx,
LayoutStore webLayoutManager,
List<WidgetDefinitionConverter> widgetConverters) {
String widgetName = widgetRef.getName();
WidgetDefinition widgetDef = layoutDef.getWidgetDefinition(widgetName);
if (widgetDef == null) {
String cat = widgetRef.getCategory();
if (cat == null) {
cat = category;
}
widgetDef = webLayoutManager.getWidgetDefinition(cat, widgetName);
}
if (widgetDef == null) {
log.error(String.format(
"No definition found for widget '%s' in layout '%s' "
+ "=> cannot export", widgetName,
layoutDef.getName()));
} else {
if (widgetConverters != null) {
for (WidgetDefinitionConverter conv : widgetConverters) {
widgetDef = conv.getWidgetDefinition(widgetDef, ctx);
}
}
}
return widgetDef;
}
@SuppressWarnings("unchecked")
public static LayoutDefinition importLayoutDefinition(JSONObject layoutDef) {
String name = layoutDef.optString("name", null);
String type = layoutDef.optString("type", null);
String typeCat = layoutDef.optString("typeCategory", null);
Map<String, String> templates = importStringProps(layoutDef.optJSONObject("templates"));
Map<String, Map<String, Serializable>> properties = importPropsByMode(layoutDef.optJSONObject("properties"));
List<LayoutRowDefinition> rows = new ArrayList<LayoutRowDefinition>();
JSONArray jrows = layoutDef.optJSONArray("rows");
if (jrows != null) {
for (Object item : jrows) {
rows.add(importLayoutRowDefinition((JSONObject) item));
}
}
List<WidgetDefinition> widgets = new ArrayList<WidgetDefinition>();
JSONArray jwidgets = layoutDef.optJSONArray("widgets");
if (jwidgets != null) {
for (Object item : jwidgets) {
widgets.add(importWidgetDefinition((JSONObject) item));
}
}
Map<String, List<RenderingInfo>> renderingInfos = importRenderingInfosByMode(layoutDef.optJSONObject("renderingInfos"));
List<String> aliases = new ArrayList<String>();
JSONArray jaliases = layoutDef.optJSONArray("aliases");
if (jaliases != null) {
aliases.addAll(jaliases);
}
LayoutDefinitionImpl res = new LayoutDefinitionImpl(name, properties,
templates, rows, widgets);
res.setRenderingInfos(renderingInfos);
res.setType(type);
res.setTypeCategory(typeCat);
res.setAliases(aliases);
return res;
}
/**
* @since 6.0
*/
public static JSONObject exportToJson(LayoutRowDefinition layoutRowDef,
String defaultRowName) {
JSONObject json = new JSONObject();
String name = layoutRowDef.getName();
if (name != null) {
json.element("name", name);
} else if (defaultRowName != null) {
json.element("name", defaultRowName);
}
// fill selection info only if that's not the default value from the
// definition
if (layoutRowDef.isAlwaysSelected()) {
json.element("alwaysSelected", true);
}
if (!layoutRowDef.isSelectedByDefault()) {
json.element("selectedByDefault", false);
}
layoutRowDef.isSelectedByDefault();
JSONObject props = exportPropsByModeToJson(layoutRowDef.getProperties());
if (!props.isEmpty()) {
json.element("properties", props);
}
JSONArray widgets = new JSONArray();
WidgetReference[] defWidgets = layoutRowDef.getWidgetReferences();
if (defWidgets != null) {
for (WidgetReference widget : defWidgets) {
widgets.add(exportToJson(widget));
}
}
if (!widgets.isEmpty()) {
json.element("widgets", widgets);
}
return json;
}
public static JSONObject exportToJson(LayoutRowDefinition layoutRowDef) {
return exportToJson(layoutRowDef, null);
}
public static LayoutRowDefinition importLayoutRowDefinition(
JSONObject layoutRowDef) {
String name = layoutRowDef.optString("name", null);
boolean alwaysSelected = layoutRowDef.optBoolean("alwaysSelected",
false);
boolean selectedByDefault = layoutRowDef.optBoolean(
"selectedByDefault", true);
Map<String, Map<String, Serializable>> properties = importPropsByMode(layoutRowDef.optJSONObject("properties"));
List<WidgetReference> widgets = new ArrayList<WidgetReference>();
JSONArray jwidgets = layoutRowDef.optJSONArray("widgets");
if (jwidgets != null) {
for (Object item : jwidgets) {
if (item instanceof String) {
// BBB
widgets.add(new WidgetReferenceImpl((String) item));
} else {
widgets.add(importWidgetReference((JSONObject) item));
}
}
}
return new LayoutRowDefinitionImpl(name, properties, widgets,
alwaysSelected, selectedByDefault);
}
/**
* @since 5.5
* @param widgetDef
* @param ctx
* @param widgetConverters
* @return
*/
@SuppressWarnings("deprecation")
public static JSONObject exportToJson(WidgetDefinition widgetDef,
LayoutConversionContext ctx,
List<WidgetDefinitionConverter> widgetConverters) {
JSONObject json = new JSONObject();
json.element("name", widgetDef.getName());
json.element("type", widgetDef.getType());
json.element("typeCategory", widgetDef.getTypeCategory());
JSONObject labels = exportStringPropsToJson(widgetDef.getLabels());
if (!labels.isEmpty()) {
json.element("labels", labels);
}
JSONObject helpLabels = exportStringPropsToJson(widgetDef.getHelpLabels());
if (!helpLabels.isEmpty()) {
json.element("helpLabels", helpLabels);
}
json.element("translated", widgetDef.isTranslated());
json.element("handlingLabels", widgetDef.isHandlingLabels());
JSONObject widgetModes = exportStringPropsToJson(widgetDef.getModes());
if (!widgetModes.isEmpty()) {
json.element("widgetModes", widgetModes);
}
JSONArray fields = new JSONArray();
FieldDefinition[] fieldDefs = widgetDef.getFieldDefinitions();
if (fieldDefs != null) {
for (FieldDefinition fieldDef : fieldDefs) {
fields.add(exportToJson(fieldDef));
}
}
if (!fields.isEmpty()) {
json.element("fields", fields);
}
JSONArray subWidgets = new JSONArray();
WidgetDefinition[] subWidgetDefs = widgetDef.getSubWidgetDefinitions();
if (subWidgetDefs != null) {
for (WidgetDefinition wDef : subWidgetDefs) {
subWidgets.add(exportToJson(wDef, ctx, widgetConverters));
}
}
if (!subWidgets.isEmpty()) {
json.element("subWidgets", subWidgets);
}
JSONArray subWidgetRefs = new JSONArray();
WidgetReference[] subWidgetRefDefs = widgetDef.getSubWidgetReferences();
if (subWidgetRefDefs != null) {
for (WidgetReference ref : subWidgetRefDefs) {
subWidgetRefs.add(exportToJson(ref));
}
}
if (!subWidgetRefs.isEmpty()) {
json.element("subWidgetRefs", subWidgetRefs);
}
JSONObject props = exportPropsByModeToJson(widgetDef.getProperties());
if (!props.isEmpty()) {
json.element("properties", props);
}
JSONObject widgetModeProps = exportPropsByModeToJson(widgetDef.getWidgetModeProperties());
if (!widgetModeProps.isEmpty()) {
json.element("propertiesByWidgetMode", widgetModeProps);
}
JSONObject controls = exportPropsByModeToJson(widgetDef.getControls());
if (!controls.isEmpty()) {
json.element("controls", controls);
}
JSONArray selectOptions = new JSONArray();
WidgetSelectOption[] selectOptionDefs = widgetDef.getSelectOptions();
if (selectOptionDefs != null) {
for (WidgetSelectOption selectOptionDef : selectOptionDefs) {
selectOptions.add(exportToJson(selectOptionDef));
}
}
if (!selectOptions.isEmpty()) {
json.element("selectOptions", selectOptions);
}
JSONObject renderingInfos = exportRenderingInfosByModeToJson(widgetDef.getRenderingInfos());
if (!renderingInfos.isEmpty()) {
json.element("renderingInfos", renderingInfos);
}
List<String> caliases = widgetDef.getAliases();
if (caliases != null && !caliases.isEmpty()) {
JSONArray aliases = new JSONArray();
for (String alias : caliases) {
aliases.add(alias);
}
json.element("aliases", aliases);
}
return json;
}
@SuppressWarnings({ "unchecked" })
public static WidgetDefinition importWidgetDefinition(JSONObject widgetDef) {
String name = widgetDef.getString("name");
String type = widgetDef.getString("type");
String typeCategory = widgetDef.optString("typeCategory");
Map<String, String> labels = importStringProps(widgetDef.optJSONObject("labels"));
Map<String, String> helpLabels = importStringProps(widgetDef.optJSONObject("helpLabels"));
boolean translated = widgetDef.optBoolean("translated", false);
boolean handlingLabels = widgetDef.optBoolean("handlingLabels", false);
Map<String, String> modes = importStringProps(widgetDef.optJSONObject("widgetModes"));
List<FieldDefinition> fieldDefinitions = new ArrayList<FieldDefinition>();
JSONArray jfields = widgetDef.optJSONArray("fields");
if (jfields != null) {
for (Object item : jfields) {
fieldDefinitions.add(importFieldDefinition((JSONObject) item));
}
}
List<WidgetDefinition> subWidgets = new ArrayList<WidgetDefinition>();
JSONArray jsubwidgets = widgetDef.optJSONArray("subWidgets");
if (jsubwidgets != null) {
for (Object item : jsubwidgets) {
subWidgets.add(importWidgetDefinition((JSONObject) item));
}
}
List<WidgetReference> subWidgetRefs = new ArrayList<WidgetReference>();
JSONArray jsubwidgetRefs = widgetDef.optJSONArray("subWidgetRefs");
if (jsubwidgetRefs != null) {
for (Object item : jsubwidgetRefs) {
subWidgetRefs.add(importWidgetReference((JSONObject) item));
}
}
Map<String, Map<String, Serializable>> properties = importPropsByMode(widgetDef.optJSONObject("properties"));
Map<String, Map<String, Serializable>> widgetModeProperties = importPropsByMode(widgetDef.optJSONObject("propertiesByWidgetMode"));
Map<String, Map<String, Serializable>> controls = importPropsByMode(widgetDef.optJSONObject("controls"));
// select options
List<WidgetSelectOption> selectOptions = new ArrayList<WidgetSelectOption>();
JSONArray jselectOptions = widgetDef.optJSONArray("selectOptions");
if (jselectOptions != null) {
for (Object item : jselectOptions) {
selectOptions.add(importWidgetSelectionOption((JSONObject) item));
}
}
Map<String, List<RenderingInfo>> renderingInfos = importRenderingInfosByMode(widgetDef.optJSONObject("renderingInfos"));
List<String> aliases = new ArrayList<String>();
JSONArray jaliases = widgetDef.optJSONArray("aliases");
if (jaliases != null) {
aliases.addAll(jaliases);
}
WidgetDefinitionImpl res = new WidgetDefinitionImpl(name, type, labels,
helpLabels, translated, modes,
fieldDefinitions.toArray(new FieldDefinition[] {}), properties,
widgetModeProperties,
subWidgets.toArray(new WidgetDefinition[] {}),
selectOptions.toArray(new WidgetSelectOption[] {}));
res.setRenderingInfos(renderingInfos);
res.setSubWidgetReferences(subWidgetRefs.toArray(new WidgetReference[] {}));
res.setHandlingLabels(handlingLabels);
res.setControls(controls);
res.setTypeCategory(typeCategory);
res.setAliases(aliases);
return res;
}
public static JSONObject exportToJson(FieldDefinition fieldDef) {
JSONObject json = new JSONObject();
json.element("fieldName", fieldDef.getFieldName());
json.element("schemaName", fieldDef.getSchemaName());
json.element("propertyName", fieldDef.getPropertyName());
return json;
}
public static FieldDefinition importFieldDefinition(JSONObject fieldDef) {
// ignore property name: it can be deduced from schema and field name
FieldDefinition res = new FieldDefinitionImpl(fieldDef.optString(
"schemaName", null), fieldDef.getString("fieldName"));
return res;
}
public static JSONObject exportToJson(WidgetReference widgetRef) {
JSONObject json = new JSONObject();
json.element("name", widgetRef.getName());
json.element("category", widgetRef.getCategory());
return json;
}
public static WidgetReference importWidgetReference(JSONObject widgetRef) {
WidgetReference res = new WidgetReferenceImpl(
widgetRef.optString("category"), widgetRef.optString("name",
null));
return res;
}
public static JSONObject exportToJson(WidgetSelectOption selectOption) {
JSONObject json = new JSONObject();
Serializable value = selectOption.getValue();
boolean isMulti = selectOption instanceof WidgetSelectOptions;
if (isMulti) {
json.element("multiple", true);
} else {
json.element("multiple", false);
}
if (value != null) {
json.element("value", value);
}
String var = selectOption.getVar();
if (var != null) {
json.element("var", var);
}
String itemLabel = selectOption.getItemLabel();
if (itemLabel != null) {
json.element("itemLabel", itemLabel);
}
Map<String, String> labels = selectOption.getItemLabels();
if (labels != null && !labels.isEmpty()) {
JSONObject jsonLabels = new JSONObject();
for (Map.Entry<String, String> entry : labels.entrySet()) {
jsonLabels.put(entry.getKey(), entry.getValue());
}
json.element("itemLabels", jsonLabels);
}
String itemValue = selectOption.getItemValue();
if (itemValue != null) {
json.element("itemValue", itemValue);
}
Serializable itemDisabled = selectOption.getItemDisabled();
if (itemDisabled != null) {
json.element("itemDisabled", itemDisabled);
}
Serializable itemRendered = selectOption.getItemRendered();
if (itemRendered != null) {
json.element("itemRendered", itemRendered);
}
if (isMulti) {
WidgetSelectOptions selectOptions = (WidgetSelectOptions) selectOption;
String ordering = selectOptions.getOrdering();
if (ordering != null) {
json.element("ordering", ordering);
}
Boolean caseSensitive = selectOptions.getCaseSensitive();
if (caseSensitive != null) {
json.element("caseSensitive", caseSensitive);
}
}
return json;
}
@SuppressWarnings("unchecked")
public static WidgetSelectOption importWidgetSelectionOption(
JSONObject selectOption) {
boolean isMulti = selectOption.getBoolean("multiple");
Serializable value = selectOption.optString("value", null);
String var = selectOption.optString("var", null);
String itemLabel = selectOption.optString("itemLabel", null);
Map<String, String> labels = new HashMap<String, String>();
JSONObject jsonLabels = selectOption.optJSONObject("itemLabels");
if (jsonLabels != null && !jsonLabels.isNullObject()) {
labels.putAll(jsonLabels);
}
String itemValue = selectOption.optString("itemValue", null);
Serializable itemDisabled = selectOption.optString("itemDisabled", null);
Serializable itemRendered = selectOption.optString("itemRendered", null);
if (isMulti) {
String ordering = selectOption.optString("ordering", null);
Boolean caseSensitive = null;
if (selectOption.has("caseSensitive")) {
caseSensitive = new Boolean(
selectOption.getBoolean("caseSensitive"));
}
WidgetSelectOptionsImpl res = new WidgetSelectOptionsImpl(value,
var, itemLabel, itemValue, itemDisabled, itemRendered,
ordering, caseSensitive);
res.setItemLabels(labels);
return res;
} else {
WidgetSelectOptionImpl res = new WidgetSelectOptionImpl(value, var,
itemLabel, itemValue, itemDisabled, itemRendered);
res.setItemLabels(labels);
return res;
}
}
public static JSONObject exportPropsByModeToJson(
Map<String, Map<String, Serializable>> propsByMode) {
JSONObject props = new JSONObject();
if (propsByMode != null) {
List<String> defModes = new ArrayList<String>(propsByMode.keySet());
// sort so that order is deterministic
Collections.sort(defModes);
for (String defMode : defModes) {
props.element(defMode,
exportPropsToJson(propsByMode.get(defMode)));
}
}
return props;
}
@SuppressWarnings("unchecked")
public static Map<String, Map<String, Serializable>> importPropsByMode(
JSONObject propsByMode) {
Map<String, Map<String, Serializable>> props = new HashMap<String, Map<String, Serializable>>();
if (propsByMode != null && !propsByMode.isNullObject()) {
List<String> defModes = new ArrayList<String>(propsByMode.keySet());
// sort so that order is deterministic
Collections.sort(defModes);
for (String defMode : defModes) {
props.put(defMode,
importProps(propsByMode.getJSONObject(defMode)));
}
}
return props;
}
@SuppressWarnings({ "rawtypes" })
public static JSONObject exportPropsToJson(
Map<String, Serializable> defProps) {
JSONObject props = new JSONObject();
if (defProps != null) {
List<String> defPropNames = new ArrayList<String>(defProps.keySet());
// sort so that order is deterministic
Collections.sort(defPropNames);
for (String defPropName : defPropNames) {
Serializable value = defProps.get(defPropName);
if (value instanceof Collection) {
JSONArray array = new JSONArray();
array.addAll((Collection) value);
props.element(defPropName, array);
} else if (value instanceof Object[]) {
JSONArray array = new JSONArray();
for (Object item : (Object[]) value) {
array.add(item);
}
props.element(defPropName, array);
} else {
props.element(defPropName, value);
}
}
}
return props;
}
@SuppressWarnings("unchecked")
public static Map<String, Serializable> importProps(JSONObject defProps) {
Map<String, Serializable> props = new HashMap<String, Serializable>();
if (defProps != null && !defProps.isNullObject()) {
List<String> defPropNames = new ArrayList<String>(defProps.keySet());
// sort so that order is deterministic
Collections.sort(defPropNames);
for (String defPropName : defPropNames) {
Object value = defProps.opt(defPropName);
if (value instanceof JSONArray) {
ArrayList<Object> listValue = new ArrayList<Object>();
listValue.addAll(((JSONArray) value));
} else {
props.put(defPropName, value.toString());
}
}
}
return props;
}
public static JSONObject exportStringPropsToJson(
Map<String, String> defProps) {
JSONObject props = new JSONObject();
if (defProps != null) {
List<String> defPropNames = new ArrayList<String>(defProps.keySet());
// sort so that order is deterministic
Collections.sort(defPropNames);
for (String defPropName : defPropNames) {
props.element(defPropName, defProps.get(defPropName));
}
}
return props;
}
public static Map<String, String> importStringProps(JSONObject defProps) {
Map<String, String> props = new HashMap<String, String>();
if (defProps != null && !defProps.isNullObject()) {
for (Object item : defProps.keySet()) {
String key = (String) item;
props.put(key, defProps.getString(key));
}
}
return props;
}
public static JSONObject exportRenderingInfosByModeToJson(
Map<String, List<RenderingInfo>> infosByMode) {
JSONObject props = new JSONObject();
if (infosByMode != null) {
List<String> defModes = new ArrayList<String>(infosByMode.keySet());
// sort so that order is deterministic
Collections.sort(defModes);
for (String defMode : defModes) {
props.element(defMode,
exportRenderingInfosToJson(infosByMode.get(defMode)));
}
}
return props;
}
@SuppressWarnings("unchecked")
public static Map<String, List<RenderingInfo>> importRenderingInfosByMode(
JSONObject infosByMode) {
Map<String, List<RenderingInfo>> props = new HashMap<String, List<RenderingInfo>>();
if (infosByMode != null && !infosByMode.isNullObject()) {
List<String> defModes = new ArrayList<String>(infosByMode.keySet());
// sort so that order is deterministic
Collections.sort(defModes);
for (String defMode : defModes) {
props.put(defMode,
importRenderingInfos(infosByMode.getJSONArray(defMode)));
}
}
return props;
}
public static JSONArray exportRenderingInfosToJson(List<RenderingInfo> infos) {
JSONArray jinfos = new JSONArray();
if (infos != null) {
for (RenderingInfo info : infos) {
jinfos.add(exportToJson(info));
}
}
return jinfos;
}
public static List<RenderingInfo> importRenderingInfos(JSONArray jinfos) {
List<RenderingInfo> infos = new ArrayList<RenderingInfo>();
if (jinfos != null) {
for (Object item : jinfos) {
infos.add(importRenderingInfo((JSONObject) item));
}
}
return infos;
}
public static JSONObject exportToJson(RenderingInfo info) {
JSONObject json = new JSONObject();
json.element("level", info.getLevel());
json.element("message", info.getMessage());
json.element("translated", info.isTranslated());
return json;
}
public static RenderingInfo importRenderingInfo(JSONObject fieldDef) {
RenderingInfo res = new RenderingInfoImpl(fieldDef.optString("level",
""), fieldDef.optString("message"), fieldDef.optBoolean(
"translated", false));
return res;
}
}