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