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