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