001/* 002 * (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Anahide Tchertchian 016 */ 017package org.nuxeo.ecm.platform.forms.layout.io; 018 019import java.io.IOException; 020import java.io.OutputStream; 021import java.io.Serializable; 022import java.io.UnsupportedEncodingException; 023import java.net.URLDecoder; 024import java.net.URLEncoder; 025import java.util.ArrayList; 026import java.util.Collection; 027import java.util.Collections; 028import java.util.HashMap; 029import java.util.List; 030import java.util.Map; 031 032import net.sf.json.JSONArray; 033import net.sf.json.JSONObject; 034 035import org.apache.commons.lang.StringUtils; 036import org.apache.commons.logging.Log; 037import org.apache.commons.logging.LogFactory; 038import org.nuxeo.ecm.platform.forms.layout.api.FieldDefinition; 039import org.nuxeo.ecm.platform.forms.layout.api.Layout; 040import org.nuxeo.ecm.platform.forms.layout.api.LayoutDefinition; 041import org.nuxeo.ecm.platform.forms.layout.api.LayoutRow; 042import org.nuxeo.ecm.platform.forms.layout.api.LayoutRowDefinition; 043import org.nuxeo.ecm.platform.forms.layout.api.LayoutTypeConfiguration; 044import org.nuxeo.ecm.platform.forms.layout.api.LayoutTypeDefinition; 045import org.nuxeo.ecm.platform.forms.layout.api.RenderingInfo; 046import org.nuxeo.ecm.platform.forms.layout.api.Widget; 047import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; 048import org.nuxeo.ecm.platform.forms.layout.api.WidgetReference; 049import org.nuxeo.ecm.platform.forms.layout.api.WidgetSelectOption; 050import org.nuxeo.ecm.platform.forms.layout.api.WidgetSelectOptions; 051import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeConfiguration; 052import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeDefinition; 053import org.nuxeo.ecm.platform.forms.layout.api.converters.LayoutConversionContext; 054import org.nuxeo.ecm.platform.forms.layout.api.converters.WidgetDefinitionConverter; 055import org.nuxeo.ecm.platform.forms.layout.api.impl.FieldDefinitionImpl; 056import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutDefinitionImpl; 057import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutRowDefinitionImpl; 058import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutTypeConfigurationImpl; 059import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutTypeDefinitionComparator; 060import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutTypeDefinitionImpl; 061import org.nuxeo.ecm.platform.forms.layout.api.impl.RenderingInfoImpl; 062import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetDefinitionImpl; 063import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetReferenceImpl; 064import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetSelectOptionImpl; 065import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetSelectOptionsImpl; 066import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeConfigurationImpl; 067import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeDefinitionComparator; 068import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetTypeDefinitionImpl; 069import org.nuxeo.ecm.platform.forms.layout.api.service.LayoutStore; 070import org.nuxeo.runtime.api.Framework; 071 072/** 073 * JSON exporter for layout objects 074 * 075 * @author Anahide Tchertchian 076 * @since 5.4.2 077 */ 078public class JSONLayoutExporter { 079 080 private static final Log log = LogFactory.getLog(JSONLayoutExporter.class); 081 082 public static final String ENCODED_VALUES_ENCODING = "UTF-8"; 083 084 public static String encode(JSONObject jsonObject) throws UnsupportedEncodingException { 085 String json = jsonObject.toString(); 086 String encodedValues = Base64.encodeBytes(json.getBytes(), Base64.GZIP | Base64.DONT_BREAK_LINES); 087 return URLEncoder.encode(encodedValues, ENCODED_VALUES_ENCODING); 088 } 089 090 public static JSONObject decode(String json) throws UnsupportedEncodingException { 091 String decodedValues = URLDecoder.decode(json, ENCODED_VALUES_ENCODING); 092 json = new String(Base64.decode(decodedValues)); 093 return JSONObject.fromObject(json); 094 } 095 096 /** 097 * @since 5.5 098 * @throws IOException 099 */ 100 public static void export(String category, LayoutDefinition layoutDef, LayoutConversionContext ctx, 101 List<WidgetDefinitionConverter> widgetConverters, OutputStream out) throws IOException { 102 JSONObject res = exportToJson(category, layoutDef, ctx, widgetConverters); 103 out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING)); 104 } 105 106 public static void export(WidgetTypeDefinition def, OutputStream out) throws IOException { 107 JSONObject res = exportToJson(def); 108 out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING)); 109 } 110 111 public static void export(List<WidgetTypeDefinition> defs, OutputStream out) throws IOException { 112 JSONObject res = new JSONObject(); 113 if (defs != null) { 114 // sort so that order is deterministic 115 Collections.sort(defs, new WidgetTypeDefinitionComparator(false)); 116 } 117 for (WidgetTypeDefinition def : defs) { 118 res.element(def.getName(), exportToJson(def)); 119 } 120 out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING)); 121 } 122 123 /** 124 * @since 6.0 125 */ 126 public static void exportLayoutType(LayoutTypeDefinition def, OutputStream out) throws IOException { 127 JSONObject res = exportToJson(def); 128 out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING)); 129 } 130 131 /** 132 * @since 6.0 133 */ 134 public static void exportLayoutTypes(List<LayoutTypeDefinition> defs, OutputStream out) throws IOException { 135 JSONObject res = new JSONObject(); 136 if (defs != null) { 137 // sort so that order is deterministic 138 Collections.sort(defs, new LayoutTypeDefinitionComparator()); 139 } 140 for (LayoutTypeDefinition def : defs) { 141 res.element(def.getName(), exportToJson(def)); 142 } 143 out.write(res.toString(2).getBytes(ENCODED_VALUES_ENCODING)); 144 } 145 146 public static JSONObject exportToJson(WidgetTypeDefinition def) { 147 JSONObject json = new JSONObject(); 148 json.element("name", def.getName()); 149 List<String> caliases = def.getAliases(); 150 if (caliases != null && !caliases.isEmpty()) { 151 JSONArray aliases = new JSONArray(); 152 for (String alias : caliases) { 153 aliases.add(alias); 154 } 155 json.element("aliases", aliases); 156 } 157 json.element("handlerClassName", def.getHandlerClassName()); 158 JSONObject props = exportStringPropsToJson(def.getProperties()); 159 if (!props.isEmpty()) { 160 json.element("properties", props); 161 } 162 WidgetTypeConfiguration conf = def.getConfiguration(); 163 if (conf != null) { 164 json.element("configuration", exportToJson(conf)); 165 } 166 return json; 167 } 168 169 @SuppressWarnings("unchecked") 170 public static WidgetTypeDefinition importWidgetTypeDefinition(JSONObject jsonDef) { 171 String name = jsonDef.optString("name"); 172 String handlerClass = jsonDef.optString("handlerClassName"); 173 Map<String, String> properties = importStringProps(jsonDef.optJSONObject("properties")); 174 WidgetTypeConfiguration conf = importWidgetTypeConfiguration(jsonDef.optJSONObject("configuration")); 175 List<String> aliases = new ArrayList<String>(); 176 JSONArray jaliases = jsonDef.optJSONArray("aliases"); 177 if (jaliases != null) { 178 aliases.addAll(jaliases); 179 } 180 WidgetTypeDefinitionImpl res = new WidgetTypeDefinitionImpl(name, handlerClass, properties, conf); 181 res.setAliases(aliases); 182 return res; 183 } 184 185 public static JSONObject exportToJson(WidgetTypeConfiguration conf) { 186 JSONObject json = new JSONObject(); 187 json.element("title", conf.getTitle()); 188 json.element("description", conf.getDescription()); 189 String demoId = conf.getDemoId(); 190 if (demoId != null) { 191 JSONObject demoInfo = new JSONObject(); 192 demoInfo.element("id", demoId); 193 demoInfo.element("previewEnabled", conf.isDemoPreviewEnabled()); 194 json.element("demo", demoInfo); 195 } 196 json.element("sinceVersion", conf.getSinceVersion()); 197 String deprVersion = conf.getDeprecatedVersion(); 198 if (!StringUtils.isBlank(deprVersion)) { 199 json.element("deprecatedVersion", deprVersion); 200 } 201 JSONObject confProps = exportPropsToJson(conf.getConfProperties()); 202 if (!confProps.isEmpty()) { 203 json.element("confProperties", confProps); 204 } 205 206 JSONArray supportedModes = new JSONArray(); 207 List<String> confSupportedModes = conf.getSupportedModes(); 208 if (confSupportedModes != null) { 209 supportedModes.addAll(confSupportedModes); 210 } 211 if (!supportedModes.isEmpty()) { 212 json.element("supportedModes", supportedModes); 213 } 214 215 if (conf.isAcceptingSubWidgets()) { 216 json.element("acceptingSubWidgets", conf.isAcceptingSubWidgets()); 217 } 218 if (conf.isHandlingLabels()) { 219 json.element("handlingLabels", conf.isHandlingLabels()); 220 } 221 JSONArray supportedControls = new JSONArray(); 222 List<String> confSupportedControls = conf.getSupportedControls(); 223 if (confSupportedControls != null) { 224 supportedControls.addAll(confSupportedControls); 225 } 226 if (!supportedControls.isEmpty()) { 227 json.element("supportedControls", supportedControls); 228 } 229 if (conf.isContainingForm()) { 230 json.element("containingForm", true); 231 } 232 233 JSONObject fields = new JSONObject(); 234 fields.element("list", conf.isList()); 235 fields.element("complex", conf.isComplex()); 236 237 JSONArray supportedTypes = new JSONArray(); 238 List<String> confSupportedTypes = conf.getSupportedFieldTypes(); 239 if (confSupportedTypes != null) { 240 supportedTypes.addAll(confSupportedTypes); 241 } 242 if (!supportedTypes.isEmpty()) { 243 fields.element("supportedTypes", supportedTypes); 244 } 245 246 JSONArray defaultTypes = new JSONArray(); 247 List<String> confDefaultTypes = conf.getDefaultFieldTypes(); 248 if (confDefaultTypes != null) { 249 defaultTypes.addAll(confDefaultTypes); 250 } 251 if (!defaultTypes.isEmpty()) { 252 fields.element("defaultTypes", defaultTypes); 253 } 254 255 JSONArray defaultFieldDefs = new JSONArray(); 256 List<FieldDefinition> fieldDefs = conf.getDefaultFieldDefinitions(); 257 if (fieldDefs != null) { 258 for (FieldDefinition fieldDef : fieldDefs) { 259 defaultFieldDefs.add(exportToJson(fieldDef)); 260 } 261 } 262 if (!defaultFieldDefs.isEmpty()) { 263 fields.element("defaultConfiguration", defaultFieldDefs); 264 } 265 266 Map<String, List<LayoutDefinition>> fieldLayouts = conf.getFieldLayouts(); 267 if (fieldLayouts != null) { 268 List<String> modes = new ArrayList<String>(fieldLayouts.keySet()); 269 // sort so that order is deterministic 270 Collections.sort(modes); 271 JSONObject layouts = new JSONObject(); 272 for (String mode : modes) { 273 JSONArray modeLayouts = new JSONArray(); 274 for (LayoutDefinition layoutDef : fieldLayouts.get(mode)) { 275 modeLayouts.add(exportToJson(null, layoutDef)); 276 } 277 layouts.element(mode, modeLayouts); 278 } 279 if (!layouts.isEmpty()) { 280 fields.element("layouts", layouts); 281 } 282 } 283 284 json.element("fields", fields); 285 286 JSONArray cats = new JSONArray(); 287 List<String> confCats = conf.getCategories(); 288 if (confCats != null) { 289 cats.addAll(confCats); 290 } 291 if (!cats.isEmpty()) { 292 json.element("categories", cats); 293 } 294 295 JSONObject props = new JSONObject(); 296 Map<String, List<LayoutDefinition>> confLayouts = conf.getPropertyLayouts(); 297 if (confLayouts != null) { 298 List<String> modes = new ArrayList<String>(confLayouts.keySet()); 299 // sort so that order is deterministic 300 Collections.sort(modes); 301 JSONObject layouts = new JSONObject(); 302 for (String mode : modes) { 303 JSONArray modeLayouts = new JSONArray(); 304 for (LayoutDefinition layoutDef : confLayouts.get(mode)) { 305 modeLayouts.add(exportToJson(null, layoutDef)); 306 } 307 layouts.element(mode, modeLayouts); 308 } 309 if (!layouts.isEmpty()) { 310 props.element("layouts", layouts); 311 } 312 } 313 314 Map<String, Map<String, Serializable>> defaultPropValues = conf.getDefaultPropertyValues(); 315 if (defaultPropValues != null && !defaultPropValues.isEmpty()) { 316 json.element("defaultPropertyValues", exportPropsByModeToJson(defaultPropValues)); 317 } 318 319 if (!props.isEmpty()) { 320 json.element("properties", props); 321 } 322 323 Map<String, Map<String, Serializable>> defaultControlValues = conf.getDefaultControlValues(); 324 if (defaultControlValues != null && !defaultControlValues.isEmpty()) { 325 json.element("defaultControlValues", exportPropsByModeToJson(defaultControlValues)); 326 } 327 328 return json; 329 } 330 331 @SuppressWarnings("unchecked") 332 public static WidgetTypeConfiguration importWidgetTypeConfiguration(JSONObject conf) { 333 WidgetTypeConfigurationImpl res = new WidgetTypeConfigurationImpl(); 334 if (conf == null) { 335 return res; 336 } 337 res.setTitle(conf.getString("title")); 338 res.setDescription(conf.optString("description")); 339 res.setSinceVersion(conf.optString("sinceVersion")); 340 res.setDeprecatedVersion(conf.optString("deprecatedVersion")); 341 342 JSONObject demoInfo = conf.optJSONObject("demo"); 343 String demoId = null; 344 boolean demoPreviewEnabled = false; 345 if (demoInfo != null && !demoInfo.isNullObject()) { 346 demoId = demoInfo.optString("id"); 347 demoPreviewEnabled = demoInfo.optBoolean("previewEnabled"); 348 } 349 res.setDemoId(demoId); 350 res.setDemoPreviewEnabled(demoPreviewEnabled); 351 352 res.setProperties(importProps(conf.optJSONObject("confProperties"))); 353 354 List<String> confSupportedModes = new ArrayList<String>(); 355 JSONArray supportedModes = conf.optJSONArray("supportedModes"); 356 if (supportedModes != null) { 357 confSupportedModes.addAll(supportedModes); 358 } 359 res.setSupportedModes(confSupportedModes); 360 361 res.setAcceptingSubWidgets(conf.optBoolean("acceptingSubWidgets", false)); 362 res.setHandlingLabels(conf.optBoolean("handlingLabels", false)); 363 List<String> confSupportedControls = new ArrayList<String>(); 364 JSONArray supportedControls = conf.optJSONArray("supportedControls"); 365 if (supportedControls != null) { 366 confSupportedControls.addAll(supportedControls); 367 } 368 res.setSupportedControls(confSupportedControls); 369 res.setContainingForm(conf.optBoolean("containingForm", false)); 370 371 JSONObject fields = conf.optJSONObject("fields"); 372 boolean list = false; 373 boolean complex = false; 374 List<String> confSupportedTypes = new ArrayList<String>(); 375 List<String> confDefaultTypes = new ArrayList<String>(); 376 List<FieldDefinition> defaultFieldDefinitions = new ArrayList<FieldDefinition>(); 377 Map<String, List<LayoutDefinition>> fieldLayouts = new HashMap<String, List<LayoutDefinition>>(); 378 if (fields != null && !fields.isNullObject()) { 379 list = fields.optBoolean("list", false); 380 complex = fields.optBoolean("complex", false); 381 JSONArray supportedTypes = fields.optJSONArray("supportedTypes"); 382 if (supportedTypes != null) { 383 confSupportedTypes.addAll(supportedTypes); 384 } 385 JSONArray defaultTypes = fields.optJSONArray("defaultTypes"); 386 if (defaultTypes != null) { 387 confDefaultTypes.addAll(defaultTypes); 388 } 389 JSONArray jfields = fields.optJSONArray("defaultConfiguration"); 390 if (jfields != null) { 391 for (Object item : jfields) { 392 defaultFieldDefinitions.add(importFieldDefinition((JSONObject) item)); 393 } 394 } 395 JSONObject layouts = fields.optJSONObject("layouts"); 396 if (layouts != null && !layouts.isNullObject()) { 397 for (Object item : layouts.keySet()) { 398 String mode = (String) item; 399 List<LayoutDefinition> layoutDefs = new ArrayList<LayoutDefinition>(); 400 JSONArray modeLayouts = layouts.getJSONArray(mode); 401 if (modeLayouts != null && !mode.isEmpty()) { 402 for (Object subitem : modeLayouts) { 403 layoutDefs.add(importLayoutDefinition((JSONObject) subitem)); 404 } 405 } 406 fieldLayouts.put(mode, layoutDefs); 407 } 408 } 409 } 410 res.setList(list); 411 res.setComplex(complex); 412 res.setSupportedFieldTypes(confSupportedTypes); 413 res.setDefaultFieldTypes(confDefaultTypes); 414 res.setDefaultFieldDefinitions(defaultFieldDefinitions); 415 res.setFieldLayouts(fieldLayouts); 416 417 JSONArray cats = conf.optJSONArray("categories"); 418 List<String> confCats = new ArrayList<String>(); 419 if (cats != null) { 420 confCats.addAll(cats); 421 } 422 res.setCategories(confCats); 423 424 JSONObject props = conf.optJSONObject("properties"); 425 Map<String, List<LayoutDefinition>> confLayouts = new HashMap<String, List<LayoutDefinition>>(); 426 if (props != null && !props.isNullObject()) { 427 JSONObject layouts = props.optJSONObject("layouts"); 428 if (layouts != null && !layouts.isNullObject()) { 429 for (Object item : layouts.keySet()) { 430 String mode = (String) item; 431 List<LayoutDefinition> layoutDefs = new ArrayList<LayoutDefinition>(); 432 JSONArray modeLayouts = layouts.getJSONArray(mode); 433 if (modeLayouts != null && !mode.isEmpty()) { 434 for (Object subitem : modeLayouts) { 435 layoutDefs.add(importLayoutDefinition((JSONObject) subitem)); 436 } 437 } 438 confLayouts.put(mode, layoutDefs); 439 } 440 } 441 } 442 443 res.setPropertyLayouts(confLayouts); 444 445 JSONObject defaultPropertyValues = conf.optJSONObject("defaultPropertyValues"); 446 Map<String, Map<String, Serializable>> confDefaultProps = importPropsByMode(defaultPropertyValues); 447 res.setDefaultPropertyValues(confDefaultProps); 448 449 JSONObject defaultControlValues = conf.optJSONObject("defaultControlValues"); 450 Map<String, Map<String, Serializable>> confDefaultControls = importPropsByMode(defaultControlValues); 451 res.setDefaultControlValues(confDefaultControls); 452 453 return res; 454 } 455 456 /** 457 * @since 6.0 458 */ 459 public static JSONObject exportToJson(LayoutTypeDefinition def) { 460 JSONObject json = new JSONObject(); 461 json.element("name", def.getName()); 462 463 List<String> caliases = def.getAliases(); 464 if (caliases != null && !caliases.isEmpty()) { 465 JSONArray aliases = new JSONArray(); 466 for (String alias : caliases) { 467 aliases.add(alias); 468 } 469 json.element("aliases", aliases); 470 } 471 472 JSONObject templates = exportStringPropsToJson(def.getTemplates()); 473 if (!templates.isEmpty()) { 474 json.element("templates", templates); 475 } 476 477 LayoutTypeConfiguration conf = def.getConfiguration(); 478 if (conf != null) { 479 json.element("configuration", exportToJson(conf)); 480 } 481 return json; 482 } 483 484 /** 485 * @since 6.0 486 */ 487 @SuppressWarnings("unchecked") 488 public static LayoutTypeDefinition importLayoutTypeDefinition(JSONObject jsonDef) { 489 String name = jsonDef.optString("name"); 490 Map<String, String> templates = importStringProps(jsonDef.optJSONObject("templates")); 491 LayoutTypeConfiguration conf = importLayoutTypeConfiguration(jsonDef.optJSONObject("configuration")); 492 List<String> aliases = new ArrayList<String>(); 493 JSONArray jaliases = jsonDef.optJSONArray("aliases"); 494 if (jaliases != null) { 495 aliases.addAll(jaliases); 496 } 497 LayoutTypeDefinitionImpl res = new LayoutTypeDefinitionImpl(name, templates, conf); 498 res.setAliases(aliases); 499 return res; 500 } 501 502 /** 503 * @since 6.0 504 */ 505 public static JSONObject exportToJson(LayoutTypeConfiguration conf) { 506 JSONObject json = new JSONObject(); 507 json.element("title", conf.getTitle()); 508 json.element("description", conf.getDescription()); 509 String demoId = conf.getDemoId(); 510 if (demoId != null) { 511 JSONObject demoInfo = new JSONObject(); 512 demoInfo.element("id", demoId); 513 demoInfo.element("previewEnabled", conf.isDemoPreviewEnabled()); 514 json.element("demo", demoInfo); 515 } 516 json.element("sinceVersion", conf.getSinceVersion()); 517 String deprVersion = conf.getDeprecatedVersion(); 518 if (!StringUtils.isBlank(deprVersion)) { 519 json.element("deprecatedVersion", deprVersion); 520 } 521 522 JSONArray supportedModes = new JSONArray(); 523 List<String> confSupportedModes = conf.getSupportedModes(); 524 if (confSupportedModes != null) { 525 supportedModes.addAll(confSupportedModes); 526 } 527 if (!supportedModes.isEmpty()) { 528 json.element("supportedModes", supportedModes); 529 } 530 531 if (conf.isHandlingLabels()) { 532 json.element("handlingLabels", conf.isHandlingLabels()); 533 } 534 JSONArray supportedControls = new JSONArray(); 535 List<String> confSupportedControls = conf.getSupportedControls(); 536 if (confSupportedControls != null) { 537 supportedControls.addAll(confSupportedControls); 538 } 539 if (!supportedControls.isEmpty()) { 540 json.element("supportedControls", supportedControls); 541 } 542 if (conf.isContainingForm()) { 543 json.element("containingForm", true); 544 } 545 546 JSONArray cats = new JSONArray(); 547 List<String> confCats = conf.getCategories(); 548 if (confCats != null) { 549 cats.addAll(confCats); 550 } 551 if (!cats.isEmpty()) { 552 json.element("categories", cats); 553 } 554 555 JSONObject props = new JSONObject(); 556 Map<String, List<LayoutDefinition>> confLayouts = conf.getPropertyLayouts(); 557 if (confLayouts != null) { 558 List<String> modes = new ArrayList<String>(confLayouts.keySet()); 559 // sort so that order is deterministic 560 Collections.sort(modes); 561 JSONObject layouts = new JSONObject(); 562 for (String mode : modes) { 563 JSONArray modeLayouts = new JSONArray(); 564 for (LayoutDefinition layoutDef : confLayouts.get(mode)) { 565 modeLayouts.add(exportToJson(null, layoutDef)); 566 } 567 layouts.element(mode, modeLayouts); 568 } 569 if (!layouts.isEmpty()) { 570 props.element("layouts", layouts); 571 } 572 } 573 574 Map<String, Map<String, Serializable>> defaultPropValues = conf.getDefaultPropertyValues(); 575 if (defaultPropValues != null && !defaultPropValues.isEmpty()) { 576 json.element("defaultPropertyValues", exportPropsByModeToJson(defaultPropValues)); 577 } 578 579 if (!props.isEmpty()) { 580 json.element("properties", props); 581 } 582 583 return json; 584 585 } 586 587 /** 588 * @since 6.0 589 */ 590 @SuppressWarnings("unchecked") 591 public static LayoutTypeConfiguration importLayoutTypeConfiguration(JSONObject conf) { 592 LayoutTypeConfigurationImpl res = new LayoutTypeConfigurationImpl(); 593 if (conf == null) { 594 return res; 595 } 596 res.setTitle(conf.getString("title")); 597 res.setDescription(conf.optString("description")); 598 res.setSinceVersion(conf.optString("sinceVersion")); 599 res.setDeprecatedVersion(conf.optString("deprecatedVersion")); 600 601 JSONObject demoInfo = conf.optJSONObject("demo"); 602 String demoId = null; 603 boolean demoPreviewEnabled = false; 604 if (demoInfo != null && !demoInfo.isNullObject()) { 605 demoId = demoInfo.optString("id"); 606 demoPreviewEnabled = demoInfo.optBoolean("previewEnabled"); 607 } 608 res.setDemoId(demoId); 609 res.setDemoPreviewEnabled(demoPreviewEnabled); 610 611 List<String> confSupportedModes = new ArrayList<String>(); 612 JSONArray supportedModes = conf.optJSONArray("supportedModes"); 613 if (supportedModes != null) { 614 confSupportedModes.addAll(supportedModes); 615 } 616 res.setSupportedModes(confSupportedModes); 617 618 res.setHandlingLabels(conf.optBoolean("handlingLabels", false)); 619 List<String> confSupportedControls = new ArrayList<String>(); 620 JSONArray supportedControls = conf.optJSONArray("supportedControls"); 621 if (supportedControls != null) { 622 confSupportedControls.addAll(supportedControls); 623 } 624 res.setSupportedControls(confSupportedControls); 625 res.setContainingForm(conf.optBoolean("containingForm", false)); 626 627 JSONArray cats = conf.optJSONArray("categories"); 628 List<String> confCats = new ArrayList<String>(); 629 if (cats != null) { 630 confCats.addAll(cats); 631 } 632 res.setCategories(confCats); 633 634 JSONObject props = conf.optJSONObject("properties"); 635 Map<String, List<LayoutDefinition>> confLayouts = new HashMap<String, List<LayoutDefinition>>(); 636 if (props != null && !props.isNullObject()) { 637 JSONObject layouts = props.optJSONObject("layouts"); 638 if (layouts != null && !layouts.isNullObject()) { 639 for (Object item : layouts.keySet()) { 640 String mode = (String) item; 641 List<LayoutDefinition> layoutDefs = new ArrayList<LayoutDefinition>(); 642 JSONArray modeLayouts = layouts.getJSONArray(mode); 643 if (modeLayouts != null && !mode.isEmpty()) { 644 for (Object subitem : modeLayouts) { 645 layoutDefs.add(importLayoutDefinition((JSONObject) subitem)); 646 } 647 } 648 confLayouts.put(mode, layoutDefs); 649 } 650 } 651 } 652 653 res.setPropertyLayouts(confLayouts); 654 655 JSONObject defaultPropertyValues = conf.optJSONObject("defaultPropertyValues"); 656 Map<String, Map<String, Serializable>> confDefaultProps = importPropsByMode(defaultPropertyValues); 657 res.setDefaultPropertyValues(confDefaultProps); 658 659 return res; 660 } 661 662 public static JSONObject exportToJson(String category, LayoutDefinition layoutDef) { 663 return exportToJson(category, layoutDef, null, null); 664 } 665 666 /** 667 * Returns the JSON export of this layout definition 668 * 669 * @since 5.5 670 * @param category the category of the layout, needed for retrieval of referenced global widgets. 671 * @param layoutDef the layout definition 672 * @param ctx the widget conversion context 673 * @param widgetConverters the list of ordered widget converters to use before export 674 */ 675 public static JSONObject exportToJson(String category, LayoutDefinition layoutDef, LayoutConversionContext ctx, 676 List<WidgetDefinitionConverter> widgetConverters) { 677 JSONObject json = new JSONObject(); 678 json.element("name", layoutDef.getName()); 679 680 String type = layoutDef.getType(); 681 if (type != null) { 682 json.element("type", type); 683 } 684 685 String typeCat = layoutDef.getTypeCategory(); 686 if (typeCat != null) { 687 json.element("typeCategory", typeCat); 688 } 689 690 JSONObject templates = exportStringPropsToJson(layoutDef.getTemplates()); 691 if (!templates.isEmpty()) { 692 json.element("templates", templates); 693 } 694 695 JSONObject props = exportPropsByModeToJson(layoutDef.getProperties()); 696 if (!props.isEmpty()) { 697 json.element("properties", props); 698 } 699 700 JSONArray rows = new JSONArray(); 701 LayoutRowDefinition[] defRows = layoutDef.getRows(); 702 List<WidgetReference> widgetsToExport = new ArrayList<WidgetReference>(); 703 if (defRows != null) { 704 int rowIndex = -1; 705 for (LayoutRowDefinition layoutRowDef : defRows) { 706 rowIndex++; 707 rows.add(exportToJson(layoutRowDef, layoutRowDef.getDefaultName(rowIndex))); 708 WidgetReference[] widgets = layoutRowDef.getWidgetReferences(); 709 if (widgets != null) { 710 for (WidgetReference widget : widgets) { 711 widgetsToExport.add(widget); 712 } 713 } 714 } 715 } 716 717 if (!rows.isEmpty()) { 718 json.element("rows", rows); 719 } 720 LayoutStore webLayoutManager = Framework.getLocalService(LayoutStore.class); 721 JSONArray widgets = new JSONArray(); 722 for (WidgetReference widgetRef : widgetsToExport) { 723 WidgetDefinition widgetDef = exportWidgetReference(widgetRef, category, layoutDef, ctx, webLayoutManager, 724 widgetConverters); 725 if (widgetDef != null) { 726 widgets.add(exportToJson(widgetDef, ctx, widgetConverters)); 727 728 // also export local subwidgets references 729 WidgetReference[] subwidgetRefs = widgetDef.getSubWidgetReferences(); 730 if (subwidgetRefs != null) { 731 for (WidgetReference subwidgetRef : subwidgetRefs) { 732 WidgetDefinition subwidgetDef = exportWidgetReference(subwidgetRef, category, layoutDef, ctx, 733 webLayoutManager, widgetConverters); 734 if (subwidgetDef != null) { 735 widgets.add(exportToJson(subwidgetDef, ctx, widgetConverters)); 736 } 737 } 738 } 739 } 740 } 741 if (!widgets.isEmpty()) { 742 json.element("widgets", widgets); 743 } 744 745 JSONObject renderingInfos = exportRenderingInfosByModeToJson(layoutDef.getRenderingInfos()); 746 if (!renderingInfos.isEmpty()) { 747 json.element("renderingInfos", renderingInfos); 748 } 749 750 List<String> caliases = layoutDef.getAliases(); 751 if (caliases != null && !caliases.isEmpty()) { 752 JSONArray aliases = new JSONArray(); 753 for (String alias : caliases) { 754 aliases.add(alias); 755 } 756 json.element("aliases", aliases); 757 } 758 759 return json; 760 } 761 762 protected static WidgetDefinition exportWidgetReference(WidgetReference widgetRef, String category, 763 LayoutDefinition layoutDef, LayoutConversionContext ctx, LayoutStore webLayoutManager, 764 List<WidgetDefinitionConverter> widgetConverters) { 765 String widgetName = widgetRef.getName(); 766 WidgetDefinition widgetDef = layoutDef.getWidgetDefinition(widgetName); 767 if (widgetDef == null) { 768 String cat = widgetRef.getCategory(); 769 if (cat == null) { 770 cat = category; 771 } 772 widgetDef = webLayoutManager.getWidgetDefinition(cat, widgetName); 773 } 774 if (widgetDef == null) { 775 log.error(String.format("No definition found for widget '%s' in layout '%s' " + "=> cannot export", 776 widgetName, layoutDef.getName())); 777 } else { 778 if (widgetConverters != null) { 779 for (WidgetDefinitionConverter conv : widgetConverters) { 780 widgetDef = conv.getWidgetDefinition(widgetDef, ctx); 781 } 782 } 783 } 784 return widgetDef; 785 } 786 787 @SuppressWarnings("unchecked") 788 public static LayoutDefinition importLayoutDefinition(JSONObject layoutDef) { 789 String name = layoutDef.optString("name", null); 790 String type = layoutDef.optString("type", null); 791 String typeCat = layoutDef.optString("typeCategory", null); 792 Map<String, String> templates = importStringProps(layoutDef.optJSONObject("templates")); 793 Map<String, Map<String, Serializable>> properties = importPropsByMode(layoutDef.optJSONObject("properties")); 794 795 List<LayoutRowDefinition> rows = new ArrayList<LayoutRowDefinition>(); 796 JSONArray jrows = layoutDef.optJSONArray("rows"); 797 if (jrows != null) { 798 for (Object item : jrows) { 799 rows.add(importLayoutRowDefinition((JSONObject) item)); 800 } 801 } 802 803 List<WidgetDefinition> widgets = new ArrayList<WidgetDefinition>(); 804 JSONArray jwidgets = layoutDef.optJSONArray("widgets"); 805 if (jwidgets != null) { 806 for (Object item : jwidgets) { 807 widgets.add(importWidgetDefinition((JSONObject) item)); 808 } 809 } 810 811 Map<String, List<RenderingInfo>> renderingInfos = importRenderingInfosByMode(layoutDef.optJSONObject("renderingInfos")); 812 813 List<String> aliases = new ArrayList<String>(); 814 JSONArray jaliases = layoutDef.optJSONArray("aliases"); 815 if (jaliases != null) { 816 aliases.addAll(jaliases); 817 } 818 819 LayoutDefinitionImpl res = new LayoutDefinitionImpl(name, properties, templates, rows, widgets); 820 res.setRenderingInfos(renderingInfos); 821 res.setType(type); 822 res.setTypeCategory(typeCat); 823 res.setAliases(aliases); 824 return res; 825 } 826 827 /** 828 * @since 6.0 829 */ 830 public static JSONObject exportToJson(LayoutRowDefinition layoutRowDef, String defaultRowName) { 831 JSONObject json = new JSONObject(); 832 String name = layoutRowDef.getName(); 833 if (name != null) { 834 json.element("name", name); 835 } else if (defaultRowName != null) { 836 json.element("name", defaultRowName); 837 } 838 // fill selection info only if that's not the default value from the 839 // definition 840 if (layoutRowDef.isAlwaysSelected()) { 841 json.element("alwaysSelected", true); 842 } 843 if (!layoutRowDef.isSelectedByDefault()) { 844 json.element("selectedByDefault", false); 845 } 846 JSONObject props = exportPropsByModeToJson(layoutRowDef.getProperties()); 847 if (!props.isEmpty()) { 848 json.element("properties", props); 849 } 850 JSONArray widgets = new JSONArray(); 851 WidgetReference[] defWidgets = layoutRowDef.getWidgetReferences(); 852 if (defWidgets != null) { 853 for (WidgetReference widget : defWidgets) { 854 widgets.add(exportToJson(widget)); 855 } 856 } 857 if (!widgets.isEmpty()) { 858 json.element("widgets", widgets); 859 } 860 return json; 861 } 862 863 public static JSONObject exportToJson(LayoutRowDefinition layoutRowDef) { 864 return exportToJson(layoutRowDef, null); 865 } 866 867 public static LayoutRowDefinition importLayoutRowDefinition(JSONObject layoutRowDef) { 868 String name = layoutRowDef.optString("name", null); 869 870 boolean alwaysSelected = layoutRowDef.optBoolean("alwaysSelected", false); 871 boolean selectedByDefault = layoutRowDef.optBoolean("selectedByDefault", true); 872 873 Map<String, Map<String, Serializable>> properties = importPropsByMode(layoutRowDef.optJSONObject("properties")); 874 875 List<WidgetReference> widgets = new ArrayList<WidgetReference>(); 876 JSONArray jwidgets = layoutRowDef.optJSONArray("widgets"); 877 if (jwidgets != null) { 878 for (Object item : jwidgets) { 879 if (item instanceof String) { 880 // BBB 881 widgets.add(new WidgetReferenceImpl((String) item)); 882 } else { 883 widgets.add(importWidgetReference((JSONObject) item)); 884 } 885 } 886 } 887 return new LayoutRowDefinitionImpl(name, properties, widgets, alwaysSelected, selectedByDefault); 888 } 889 890 /** 891 * @since 5.5 892 * @param widgetDef 893 * @param ctx 894 * @param widgetConverters 895 * @return 896 */ 897 @SuppressWarnings("deprecation") 898 public static JSONObject exportToJson(WidgetDefinition widgetDef, LayoutConversionContext ctx, 899 List<WidgetDefinitionConverter> widgetConverters) { 900 JSONObject json = new JSONObject(); 901 json.element("name", widgetDef.getName()); 902 json.element("type", widgetDef.getType()); 903 json.element("typeCategory", widgetDef.getTypeCategory()); 904 JSONObject labels = exportStringPropsToJson(widgetDef.getLabels()); 905 if (!labels.isEmpty()) { 906 json.element("labels", labels); 907 } 908 JSONObject helpLabels = exportStringPropsToJson(widgetDef.getHelpLabels()); 909 if (!helpLabels.isEmpty()) { 910 json.element("helpLabels", helpLabels); 911 } 912 json.element("translated", widgetDef.isTranslated()); 913 json.element("handlingLabels", widgetDef.isHandlingLabels()); 914 JSONObject widgetModes = exportStringPropsToJson(widgetDef.getModes()); 915 if (!widgetModes.isEmpty()) { 916 json.element("widgetModes", widgetModes); 917 } 918 919 JSONArray fields = new JSONArray(); 920 FieldDefinition[] fieldDefs = widgetDef.getFieldDefinitions(); 921 if (fieldDefs != null) { 922 for (FieldDefinition fieldDef : fieldDefs) { 923 fields.add(exportToJson(fieldDef)); 924 } 925 } 926 if (!fields.isEmpty()) { 927 json.element("fields", fields); 928 } 929 930 JSONArray subWidgets = new JSONArray(); 931 WidgetDefinition[] subWidgetDefs = widgetDef.getSubWidgetDefinitions(); 932 if (subWidgetDefs != null) { 933 for (WidgetDefinition wDef : subWidgetDefs) { 934 subWidgets.add(exportToJson(wDef, ctx, widgetConverters)); 935 } 936 } 937 if (!subWidgets.isEmpty()) { 938 json.element("subWidgets", subWidgets); 939 } 940 941 JSONArray subWidgetRefs = new JSONArray(); 942 WidgetReference[] subWidgetRefDefs = widgetDef.getSubWidgetReferences(); 943 if (subWidgetRefDefs != null) { 944 for (WidgetReference ref : subWidgetRefDefs) { 945 subWidgetRefs.add(exportToJson(ref)); 946 } 947 } 948 if (!subWidgetRefs.isEmpty()) { 949 json.element("subWidgetRefs", subWidgetRefs); 950 } 951 952 JSONObject props = exportPropsByModeToJson(widgetDef.getProperties()); 953 if (!props.isEmpty()) { 954 json.element("properties", props); 955 } 956 JSONObject widgetModeProps = exportPropsByModeToJson(widgetDef.getWidgetModeProperties()); 957 if (!widgetModeProps.isEmpty()) { 958 json.element("propertiesByWidgetMode", widgetModeProps); 959 } 960 961 JSONObject controls = exportPropsByModeToJson(widgetDef.getControls()); 962 if (!controls.isEmpty()) { 963 json.element("controls", controls); 964 } 965 966 JSONArray selectOptions = new JSONArray(); 967 WidgetSelectOption[] selectOptionDefs = widgetDef.getSelectOptions(); 968 if (selectOptionDefs != null) { 969 for (WidgetSelectOption selectOptionDef : selectOptionDefs) { 970 selectOptions.add(exportToJson(selectOptionDef)); 971 } 972 } 973 if (!selectOptions.isEmpty()) { 974 json.element("selectOptions", selectOptions); 975 } 976 977 JSONObject renderingInfos = exportRenderingInfosByModeToJson(widgetDef.getRenderingInfos()); 978 if (!renderingInfos.isEmpty()) { 979 json.element("renderingInfos", renderingInfos); 980 } 981 982 List<String> caliases = widgetDef.getAliases(); 983 if (caliases != null && !caliases.isEmpty()) { 984 JSONArray aliases = new JSONArray(); 985 for (String alias : caliases) { 986 aliases.add(alias); 987 } 988 json.element("aliases", aliases); 989 } 990 991 return json; 992 } 993 994 @SuppressWarnings({ "unchecked" }) 995 public static WidgetDefinition importWidgetDefinition(JSONObject widgetDef) { 996 String name = widgetDef.getString("name"); 997 String type = widgetDef.getString("type"); 998 String typeCategory = widgetDef.optString("typeCategory"); 999 Map<String, String> labels = importStringProps(widgetDef.optJSONObject("labels")); 1000 Map<String, String> helpLabels = importStringProps(widgetDef.optJSONObject("helpLabels")); 1001 boolean translated = widgetDef.optBoolean("translated", false); 1002 boolean handlingLabels = widgetDef.optBoolean("handlingLabels", false); 1003 Map<String, String> modes = importStringProps(widgetDef.optJSONObject("widgetModes")); 1004 1005 List<FieldDefinition> fieldDefinitions = new ArrayList<FieldDefinition>(); 1006 JSONArray jfields = widgetDef.optJSONArray("fields"); 1007 if (jfields != null) { 1008 for (Object item : jfields) { 1009 fieldDefinitions.add(importFieldDefinition((JSONObject) item)); 1010 } 1011 } 1012 1013 List<WidgetDefinition> subWidgets = new ArrayList<WidgetDefinition>(); 1014 JSONArray jsubwidgets = widgetDef.optJSONArray("subWidgets"); 1015 if (jsubwidgets != null) { 1016 for (Object item : jsubwidgets) { 1017 subWidgets.add(importWidgetDefinition((JSONObject) item)); 1018 } 1019 } 1020 1021 List<WidgetReference> subWidgetRefs = new ArrayList<WidgetReference>(); 1022 JSONArray jsubwidgetRefs = widgetDef.optJSONArray("subWidgetRefs"); 1023 if (jsubwidgetRefs != null) { 1024 for (Object item : jsubwidgetRefs) { 1025 subWidgetRefs.add(importWidgetReference((JSONObject) item)); 1026 } 1027 } 1028 1029 Map<String, Map<String, Serializable>> properties = importPropsByMode(widgetDef.optJSONObject("properties")); 1030 Map<String, Map<String, Serializable>> widgetModeProperties = importPropsByMode(widgetDef.optJSONObject("propertiesByWidgetMode")); 1031 Map<String, Map<String, Serializable>> controls = importPropsByMode(widgetDef.optJSONObject("controls")); 1032 1033 // select options 1034 List<WidgetSelectOption> selectOptions = new ArrayList<WidgetSelectOption>(); 1035 JSONArray jselectOptions = widgetDef.optJSONArray("selectOptions"); 1036 if (jselectOptions != null) { 1037 for (Object item : jselectOptions) { 1038 selectOptions.add(importWidgetSelectionOption((JSONObject) item)); 1039 } 1040 } 1041 1042 Map<String, List<RenderingInfo>> renderingInfos = importRenderingInfosByMode(widgetDef.optJSONObject("renderingInfos")); 1043 1044 List<String> aliases = new ArrayList<String>(); 1045 JSONArray jaliases = widgetDef.optJSONArray("aliases"); 1046 if (jaliases != null) { 1047 aliases.addAll(jaliases); 1048 } 1049 1050 WidgetDefinitionImpl res = new WidgetDefinitionImpl(name, type, labels, helpLabels, translated, modes, 1051 fieldDefinitions.toArray(new FieldDefinition[] {}), properties, widgetModeProperties, 1052 subWidgets.toArray(new WidgetDefinition[] {}), selectOptions.toArray(new WidgetSelectOption[] {})); 1053 res.setRenderingInfos(renderingInfos); 1054 res.setSubWidgetReferences(subWidgetRefs.toArray(new WidgetReference[] {})); 1055 res.setHandlingLabels(handlingLabels); 1056 res.setControls(controls); 1057 res.setTypeCategory(typeCategory); 1058 res.setAliases(aliases); 1059 return res; 1060 } 1061 1062 public static JSONObject exportToJson(FieldDefinition fieldDef) { 1063 JSONObject json = new JSONObject(); 1064 json.element("fieldName", fieldDef.getFieldName()); 1065 json.element("schemaName", fieldDef.getSchemaName()); 1066 json.element("propertyName", fieldDef.getPropertyName()); 1067 return json; 1068 } 1069 1070 public static FieldDefinition importFieldDefinition(JSONObject fieldDef) { 1071 // ignore property name: it can be deduced from schema and field name 1072 FieldDefinition res = new FieldDefinitionImpl(fieldDef.optString("schemaName", null), 1073 fieldDef.getString("fieldName")); 1074 return res; 1075 } 1076 1077 public static JSONObject exportToJson(WidgetReference widgetRef) { 1078 JSONObject json = new JSONObject(); 1079 json.element("name", widgetRef.getName()); 1080 json.element("category", widgetRef.getCategory()); 1081 return json; 1082 } 1083 1084 public static WidgetReference importWidgetReference(JSONObject widgetRef) { 1085 WidgetReference res = new WidgetReferenceImpl(widgetRef.optString("category"), 1086 widgetRef.optString("name", null)); 1087 return res; 1088 } 1089 1090 /** 1091 * @since 7.3 1092 */ 1093 public static JSONObject exportToJson(Layout layout) { 1094 JSONObject json = new JSONObject(); 1095 json.element("name", layout.getName()); 1096 1097 String type = layout.getType(); 1098 if (type != null) { 1099 json.element("type", type); 1100 } 1101 1102 String typeCat = layout.getTypeCategory(); 1103 if (typeCat != null) { 1104 json.element("typeCategory", typeCat); 1105 } 1106 1107 json.element("mode", layout.getMode()); 1108 1109 String template = layout.getTemplate(); 1110 if (template != null) { 1111 json.element("template", template); 1112 } 1113 1114 JSONObject props = exportPropsToJson(layout.getProperties()); 1115 if (!props.isEmpty()) { 1116 json.element("properties", props); 1117 } 1118 1119 JSONArray rows = new JSONArray(); 1120 LayoutRow[] lRows = layout.getRows(); 1121 if (lRows != null) { 1122 for (LayoutRow lRow : lRows) { 1123 rows.add(exportToJson(lRow)); 1124 } 1125 } 1126 1127 if (!rows.isEmpty()) { 1128 json.element("rows", rows); 1129 } 1130 1131 return json; 1132 } 1133 1134 /** 1135 * @since 7.3 1136 */ 1137 public static JSONObject exportToJson(LayoutRow layoutRow) { 1138 JSONObject json = new JSONObject(); 1139 String name = layoutRow.getName(); 1140 if (name != null) { 1141 json.element("name", name); 1142 } 1143 // fill selection info only if that's not the default value from the 1144 // definition 1145 if (layoutRow.isAlwaysSelected()) { 1146 json.element("alwaysSelected", true); 1147 } 1148 if (!layoutRow.isSelectedByDefault()) { 1149 json.element("selectedByDefault", false); 1150 } 1151 layoutRow.isSelectedByDefault(); 1152 JSONObject props = exportPropsToJson(layoutRow.getProperties()); 1153 if (!props.isEmpty()) { 1154 json.element("properties", props); 1155 } 1156 JSONArray widgets = new JSONArray(); 1157 Widget[] rowWidgets = layoutRow.getWidgets(); 1158 if (rowWidgets != null) { 1159 for (Widget widget : rowWidgets) { 1160 widgets.add(exportToJson(widget)); 1161 } 1162 } 1163 if (!widgets.isEmpty()) { 1164 json.element("widgets", widgets); 1165 } 1166 return json; 1167 } 1168 1169 /** 1170 * @since 7.3 1171 */ 1172 public static JSONObject exportToJson(Widget widget) { 1173 JSONObject json = new JSONObject(); 1174 json.element("name", widget.getName()); 1175 json.element("type", widget.getType()); 1176 json.element("typeCategory", widget.getTypeCategory()); 1177 json.element("mode", widget.getMode()); 1178 json.element("label", widget.getLabel()); 1179 json.element("helpLabel", widget.getHelpLabel()); 1180 json.element("translated", widget.isTranslated()); 1181 json.element("handlingLabels", widget.isHandlingLabels()); 1182 JSONArray fields = new JSONArray(); 1183 FieldDefinition[] fieldDefs = widget.getFieldDefinitions(); 1184 if (fieldDefs != null) { 1185 for (FieldDefinition fieldDef : fieldDefs) { 1186 fields.add(exportToJson(fieldDef)); 1187 } 1188 } 1189 if (!fields.isEmpty()) { 1190 json.element("fields", fields); 1191 } 1192 1193 JSONArray subWidgets = new JSONArray(); 1194 Widget[] wSubWidgets = widget.getSubWidgets(); 1195 if (wSubWidgets != null) { 1196 for (Widget wDef : wSubWidgets) { 1197 subWidgets.add(exportToJson(wDef)); 1198 } 1199 } 1200 if (!subWidgets.isEmpty()) { 1201 json.element("subWidgets", subWidgets); 1202 } 1203 1204 JSONObject props = exportPropsToJson(widget.getProperties()); 1205 if (!props.isEmpty()) { 1206 json.element("properties", props); 1207 } 1208 1209 JSONObject controls = exportPropsToJson(widget.getControls()); 1210 if (!controls.isEmpty()) { 1211 json.element("controls", controls); 1212 } 1213 1214 JSONArray selectOptions = new JSONArray(); 1215 WidgetSelectOption[] selectOptionDefs = widget.getSelectOptions(); 1216 if (selectOptionDefs != null) { 1217 for (WidgetSelectOption selectOptionDef : selectOptionDefs) { 1218 selectOptions.add(exportToJson(selectOptionDef)); 1219 } 1220 } 1221 if (!selectOptions.isEmpty()) { 1222 json.element("selectOptions", selectOptions); 1223 } 1224 1225 return json; 1226 } 1227 1228 public static JSONObject exportToJson(WidgetSelectOption selectOption) { 1229 JSONObject json = new JSONObject(); 1230 Serializable value = selectOption.getValue(); 1231 boolean isMulti = selectOption instanceof WidgetSelectOptions; 1232 if (isMulti) { 1233 json.element("multiple", true); 1234 } else { 1235 json.element("multiple", false); 1236 } 1237 if (value != null) { 1238 json.element("value", value); 1239 } 1240 String var = selectOption.getVar(); 1241 if (var != null) { 1242 json.element("var", var); 1243 } 1244 String itemLabel = selectOption.getItemLabel(); 1245 if (itemLabel != null) { 1246 json.element("itemLabel", itemLabel); 1247 } 1248 Map<String, String> labels = selectOption.getItemLabels(); 1249 if (labels != null && !labels.isEmpty()) { 1250 JSONObject jsonLabels = new JSONObject(); 1251 for (Map.Entry<String, String> entry : labels.entrySet()) { 1252 jsonLabels.put(entry.getKey(), entry.getValue()); 1253 } 1254 json.element("itemLabels", jsonLabels); 1255 } 1256 String itemValue = selectOption.getItemValue(); 1257 if (itemValue != null) { 1258 json.element("itemValue", itemValue); 1259 } 1260 Serializable itemDisabled = selectOption.getItemDisabled(); 1261 if (itemDisabled != null) { 1262 json.element("itemDisabled", itemDisabled); 1263 } 1264 Serializable itemRendered = selectOption.getItemRendered(); 1265 if (itemRendered != null) { 1266 json.element("itemRendered", itemRendered); 1267 } 1268 if (isMulti) { 1269 WidgetSelectOptions selectOptions = (WidgetSelectOptions) selectOption; 1270 String ordering = selectOptions.getOrdering(); 1271 if (ordering != null) { 1272 json.element("ordering", ordering); 1273 } 1274 Boolean caseSensitive = selectOptions.getCaseSensitive(); 1275 if (caseSensitive != null) { 1276 json.element("caseSensitive", caseSensitive); 1277 } 1278 } 1279 return json; 1280 } 1281 1282 @SuppressWarnings("unchecked") 1283 public static WidgetSelectOption importWidgetSelectionOption(JSONObject selectOption) { 1284 boolean isMulti = selectOption.getBoolean("multiple"); 1285 Serializable value = selectOption.optString("value", null); 1286 String var = selectOption.optString("var", null); 1287 String itemLabel = selectOption.optString("itemLabel", null); 1288 1289 Map<String, String> labels = new HashMap<String, String>(); 1290 JSONObject jsonLabels = selectOption.optJSONObject("itemLabels"); 1291 if (jsonLabels != null && !jsonLabels.isNullObject()) { 1292 labels.putAll(jsonLabels); 1293 } 1294 1295 String itemValue = selectOption.optString("itemValue", null); 1296 Serializable itemDisabled = selectOption.optString("itemDisabled", null); 1297 Serializable itemRendered = selectOption.optString("itemRendered", null); 1298 if (isMulti) { 1299 String ordering = selectOption.optString("ordering", null); 1300 Boolean caseSensitive = null; 1301 if (selectOption.has("caseSensitive")) { 1302 caseSensitive = new Boolean(selectOption.getBoolean("caseSensitive")); 1303 } 1304 WidgetSelectOptionsImpl res = new WidgetSelectOptionsImpl(value, var, itemLabel, itemValue, itemDisabled, 1305 itemRendered, ordering, caseSensitive); 1306 res.setItemLabels(labels); 1307 return res; 1308 } else { 1309 WidgetSelectOptionImpl res = new WidgetSelectOptionImpl(value, var, itemLabel, itemValue, itemDisabled, 1310 itemRendered); 1311 res.setItemLabels(labels); 1312 return res; 1313 } 1314 } 1315 1316 public static JSONObject exportPropsByModeToJson(Map<String, Map<String, Serializable>> propsByMode) { 1317 JSONObject props = new JSONObject(); 1318 if (propsByMode != null) { 1319 List<String> defModes = new ArrayList<String>(propsByMode.keySet()); 1320 // sort so that order is deterministic 1321 Collections.sort(defModes); 1322 for (String defMode : defModes) { 1323 props.element(defMode, exportPropsToJson(propsByMode.get(defMode))); 1324 } 1325 } 1326 return props; 1327 } 1328 1329 @SuppressWarnings("unchecked") 1330 public static Map<String, Map<String, Serializable>> importPropsByMode(JSONObject propsByMode) { 1331 Map<String, Map<String, Serializable>> props = new HashMap<String, Map<String, Serializable>>(); 1332 if (propsByMode != null && !propsByMode.isNullObject()) { 1333 List<String> defModes = new ArrayList<String>(propsByMode.keySet()); 1334 // sort so that order is deterministic 1335 Collections.sort(defModes); 1336 for (String defMode : defModes) { 1337 props.put(defMode, importProps(propsByMode.getJSONObject(defMode))); 1338 } 1339 } 1340 return props; 1341 } 1342 1343 @SuppressWarnings({ "rawtypes" }) 1344 public static JSONObject exportPropsToJson(Map<String, Serializable> defProps) { 1345 JSONObject props = new JSONObject(); 1346 if (defProps != null) { 1347 List<String> defPropNames = new ArrayList<String>(defProps.keySet()); 1348 // sort so that order is deterministic 1349 Collections.sort(defPropNames); 1350 for (String defPropName : defPropNames) { 1351 Serializable value = defProps.get(defPropName); 1352 if (value instanceof Collection) { 1353 JSONArray array = new JSONArray(); 1354 array.addAll((Collection) value); 1355 props.element(defPropName, array); 1356 } else if (value instanceof Object[]) { 1357 JSONArray array = new JSONArray(); 1358 for (Object item : (Object[]) value) { 1359 array.add(item); 1360 } 1361 props.element(defPropName, array); 1362 } else { 1363 props.element(defPropName, value); 1364 } 1365 } 1366 } 1367 return props; 1368 } 1369 1370 @SuppressWarnings("unchecked") 1371 public static Map<String, Serializable> importProps(JSONObject defProps) { 1372 Map<String, Serializable> props = new HashMap<String, Serializable>(); 1373 if (defProps != null && !defProps.isNullObject()) { 1374 List<String> defPropNames = new ArrayList<String>(defProps.keySet()); 1375 // sort so that order is deterministic 1376 Collections.sort(defPropNames); 1377 for (String defPropName : defPropNames) { 1378 Object value = defProps.opt(defPropName); 1379 if (value instanceof JSONArray) { 1380 ArrayList<Object> listValue = new ArrayList<Object>(); 1381 listValue.addAll(((JSONArray) value)); 1382 } else { 1383 props.put(defPropName, value.toString()); 1384 } 1385 } 1386 } 1387 return props; 1388 } 1389 1390 public static JSONObject exportStringPropsToJson(Map<String, String> defProps) { 1391 JSONObject props = new JSONObject(); 1392 if (defProps != null) { 1393 List<String> defPropNames = new ArrayList<String>(defProps.keySet()); 1394 // sort so that order is deterministic 1395 Collections.sort(defPropNames); 1396 for (String defPropName : defPropNames) { 1397 props.element(defPropName, defProps.get(defPropName)); 1398 } 1399 } 1400 return props; 1401 } 1402 1403 public static Map<String, String> importStringProps(JSONObject defProps) { 1404 Map<String, String> props = new HashMap<String, String>(); 1405 if (defProps != null && !defProps.isNullObject()) { 1406 for (Object item : defProps.keySet()) { 1407 String key = (String) item; 1408 props.put(key, defProps.getString(key)); 1409 } 1410 } 1411 return props; 1412 } 1413 1414 public static JSONObject exportRenderingInfosByModeToJson(Map<String, List<RenderingInfo>> infosByMode) { 1415 JSONObject props = new JSONObject(); 1416 if (infosByMode != null) { 1417 List<String> defModes = new ArrayList<String>(infosByMode.keySet()); 1418 // sort so that order is deterministic 1419 Collections.sort(defModes); 1420 for (String defMode : defModes) { 1421 props.element(defMode, exportRenderingInfosToJson(infosByMode.get(defMode))); 1422 } 1423 } 1424 return props; 1425 } 1426 1427 @SuppressWarnings("unchecked") 1428 public static Map<String, List<RenderingInfo>> importRenderingInfosByMode(JSONObject infosByMode) { 1429 Map<String, List<RenderingInfo>> props = new HashMap<String, List<RenderingInfo>>(); 1430 if (infosByMode != null && !infosByMode.isNullObject()) { 1431 List<String> defModes = new ArrayList<String>(infosByMode.keySet()); 1432 // sort so that order is deterministic 1433 Collections.sort(defModes); 1434 for (String defMode : defModes) { 1435 props.put(defMode, importRenderingInfos(infosByMode.getJSONArray(defMode))); 1436 } 1437 } 1438 return props; 1439 } 1440 1441 public static JSONArray exportRenderingInfosToJson(List<RenderingInfo> infos) { 1442 JSONArray jinfos = new JSONArray(); 1443 if (infos != null) { 1444 for (RenderingInfo info : infos) { 1445 jinfos.add(exportToJson(info)); 1446 } 1447 } 1448 return jinfos; 1449 } 1450 1451 public static List<RenderingInfo> importRenderingInfos(JSONArray jinfos) { 1452 List<RenderingInfo> infos = new ArrayList<RenderingInfo>(); 1453 if (jinfos != null) { 1454 for (Object item : jinfos) { 1455 infos.add(importRenderingInfo((JSONObject) item)); 1456 } 1457 } 1458 return infos; 1459 } 1460 1461 public static JSONObject exportToJson(RenderingInfo info) { 1462 JSONObject json = new JSONObject(); 1463 json.element("level", info.getLevel()); 1464 json.element("message", info.getMessage()); 1465 json.element("translated", info.isTranslated()); 1466 return json; 1467 } 1468 1469 public static RenderingInfo importRenderingInfo(JSONObject fieldDef) { 1470 RenderingInfo res = new RenderingInfoImpl(fieldDef.optString("level", ""), fieldDef.optString("message"), 1471 fieldDef.optBoolean("translated", false)); 1472 return res; 1473 } 1474 1475}