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.api.impl; 020 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.nuxeo.ecm.platform.forms.layout.api.BuiltinModes; 028import org.nuxeo.ecm.platform.forms.layout.api.FieldDefinition; 029import org.nuxeo.ecm.platform.forms.layout.api.RenderingInfo; 030import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; 031import org.nuxeo.ecm.platform.forms.layout.api.WidgetReference; 032import org.nuxeo.ecm.platform.forms.layout.api.WidgetSelectOption; 033 034/** 035 * Default implementation for a widget definition. 036 * <p> 037 * Useful to compute widgets independently from the layout service. 038 * 039 * @author Anahide Tchertchian 040 * @since 5.4 041 */ 042public class WidgetDefinitionImpl implements WidgetDefinition { 043 044 private static final long serialVersionUID = 1L; 045 046 protected String name; 047 048 protected String type; 049 050 protected String typeCategory; 051 052 protected Map<String, String> labels; 053 054 protected Map<String, String> helpLabels; 055 056 protected boolean translated = false; 057 058 /** 059 * @deprecated since 5.7: use {@link #controls} instead 060 */ 061 @Deprecated 062 protected boolean handlingLabels = false; 063 064 protected Map<String, String> modes; 065 066 protected FieldDefinition[] fieldDefinitions; 067 068 protected Map<String, Map<String, Serializable>> properties; 069 070 protected Map<String, Map<String, Serializable>> widgetModeProperties; 071 072 protected Map<String, Map<String, Serializable>> controls; 073 074 protected WidgetDefinition[] subWidgets; 075 076 protected WidgetReference[] subWidgetReferences; 077 078 protected WidgetSelectOption[] selectOptions; 079 080 protected Map<String, List<RenderingInfo>> renderingInfos; 081 082 protected List<String> aliases; 083 084 protected boolean dynamic = false; 085 086 protected boolean global = false; 087 088 // needed by GWT serialization 089 protected WidgetDefinitionImpl() { 090 super(); 091 } 092 093 public WidgetDefinitionImpl(String name, String type, String label, String helpLabel, boolean translated, 094 Map<String, String> modes, List<FieldDefinition> fieldDefinitions, Map<String, Serializable> properties, 095 List<WidgetDefinition> subWidgets) { 096 super(); 097 this.name = name; 098 this.type = type; 099 this.labels = new HashMap<>(); 100 if (label != null) { 101 this.labels.put(BuiltinModes.ANY, label); 102 } 103 this.helpLabels = new HashMap<>(); 104 if (helpLabel != null) { 105 this.helpLabels.put(BuiltinModes.ANY, helpLabel); 106 } 107 this.translated = translated; 108 this.modes = modes; 109 if (fieldDefinitions == null) { 110 this.fieldDefinitions = new FieldDefinition[0]; 111 } else { 112 this.fieldDefinitions = fieldDefinitions.toArray(new FieldDefinition[0]); 113 } 114 this.properties = new HashMap<>(); 115 if (properties != null) { 116 this.properties.put(BuiltinModes.ANY, properties); 117 } 118 this.widgetModeProperties = null; 119 if (subWidgets == null) { 120 this.subWidgets = new WidgetDefinition[0]; 121 } else { 122 this.subWidgets = subWidgets.toArray(new WidgetDefinition[0]); 123 } 124 } 125 126 public WidgetDefinitionImpl(String name, String type, Map<String, String> labels, Map<String, String> helpLabels, 127 boolean translated, Map<String, String> modes, List<FieldDefinition> fieldDefinitions, 128 Map<String, Map<String, Serializable>> properties, 129 Map<String, Map<String, Serializable>> widgetModeProperties, List<WidgetDefinition> subWidgets) { 130 super(); 131 this.name = name; 132 this.type = type; 133 this.labels = labels; 134 this.helpLabels = helpLabels; 135 this.translated = translated; 136 this.modes = modes; 137 if (fieldDefinitions == null) { 138 this.fieldDefinitions = new FieldDefinition[0]; 139 } else { 140 this.fieldDefinitions = fieldDefinitions.toArray(new FieldDefinition[0]); 141 } 142 this.properties = properties; 143 this.widgetModeProperties = widgetModeProperties; 144 if (subWidgets == null) { 145 this.subWidgets = new WidgetDefinition[0]; 146 } else { 147 this.subWidgets = subWidgets.toArray(new WidgetDefinition[0]); 148 } 149 } 150 151 public WidgetDefinitionImpl(String name, String type, Map<String, String> labels, Map<String, String> helpLabels, 152 boolean translated, Map<String, String> modes, FieldDefinition[] fieldDefinitions, 153 Map<String, Map<String, Serializable>> properties, 154 Map<String, Map<String, Serializable>> widgetModeProperties, WidgetDefinition[] subWidgets) { 155 super(); 156 this.name = name; 157 this.type = type; 158 this.labels = labels; 159 this.helpLabels = helpLabels; 160 this.translated = translated; 161 this.modes = modes; 162 this.fieldDefinitions = fieldDefinitions; 163 this.properties = properties; 164 this.widgetModeProperties = widgetModeProperties; 165 this.subWidgets = subWidgets; 166 } 167 168 /** 169 * @since 5.4.2 170 */ 171 public WidgetDefinitionImpl(String name, String type, Map<String, String> labels, Map<String, String> helpLabels, 172 boolean translated, Map<String, String> modes, FieldDefinition[] fieldDefinitions, 173 Map<String, Map<String, Serializable>> properties, 174 Map<String, Map<String, Serializable>> widgetModeProperties, WidgetDefinition[] subWidgets, 175 WidgetSelectOption[] selectOptions) { 176 this(name, type, labels, helpLabels, translated, modes, fieldDefinitions, properties, widgetModeProperties, 177 subWidgets); 178 this.selectOptions = selectOptions; 179 } 180 181 @Override 182 public FieldDefinition[] getFieldDefinitions() { 183 return fieldDefinitions; 184 } 185 186 @Override 187 public void setFieldDefinitions(FieldDefinition[] fieldDefinitions) { 188 this.fieldDefinitions = fieldDefinitions; 189 } 190 191 @Override 192 public String getHelpLabel(String mode) { 193 String label = helpLabels.get(mode); 194 if (label == null) { 195 label = helpLabels.get(BuiltinModes.ANY); 196 } 197 return label; 198 } 199 200 @Override 201 public Map<String, String> getHelpLabels() { 202 return helpLabels; 203 } 204 205 @Override 206 public void setHelpLabels(Map<String, String> helpLabels) { 207 this.helpLabels = helpLabels; 208 } 209 210 @Override 211 public String getLabel(String mode) { 212 String label = labels.get(mode); 213 if (label == null) { 214 label = labels.get(BuiltinModes.ANY); 215 } 216 return label; 217 } 218 219 @Override 220 public Map<String, String> getLabels() { 221 return labels; 222 } 223 224 @Override 225 public void setLabels(Map<String, String> labels) { 226 this.labels = labels; 227 } 228 229 @Override 230 public String getMode(String layoutMode) { 231 if (modes != null) { 232 String mode = modes.get(layoutMode); 233 if (mode == null) { 234 mode = modes.get(BuiltinModes.ANY); 235 } 236 return mode; 237 } 238 return null; 239 } 240 241 @Override 242 public Map<String, String> getModes() { 243 return modes; 244 } 245 246 @Override 247 public void setModes(Map<String, String> modes) { 248 this.modes = modes; 249 } 250 251 @Override 252 public String getName() { 253 return name; 254 } 255 256 @Override 257 public void setName(String name) { 258 this.name = name; 259 } 260 261 @Override 262 public Map<String, Serializable> getProperties(String layoutMode, String mode) { 263 Map<String, Serializable> modeProps = getProperties(properties, layoutMode); 264 Map<String, Serializable> widgetModeProps = getProperties(widgetModeProperties, mode); 265 // take mode values, and override with widget mode values 266 Map<String, Serializable> res = new HashMap<>(modeProps); 267 res.putAll(widgetModeProps); 268 return res; 269 } 270 271 @Override 272 public Map<String, Map<String, Serializable>> getProperties() { 273 return properties; 274 } 275 276 @Override 277 public void setProperties(Map<String, Map<String, Serializable>> properties) { 278 this.properties = properties; 279 } 280 281 @Override 282 public Map<String, Map<String, Serializable>> getWidgetModeProperties() { 283 return widgetModeProperties; 284 } 285 286 @Override 287 public void setWidgetModeProperties(Map<String, Map<String, Serializable>> widgetModeProperties) { 288 this.widgetModeProperties = widgetModeProperties; 289 } 290 291 @Override 292 public Map<String, Serializable> getControls(String layoutMode, String mode) { 293 return getProperties(controls, layoutMode); 294 } 295 296 @Override 297 public Map<String, Map<String, Serializable>> getControls() { 298 return controls; 299 } 300 301 @Override 302 public void setControls(Map<String, Map<String, Serializable>> controls) { 303 this.controls = controls; 304 } 305 306 @Override 307 public String getRequired(String layoutMode, String mode) { 308 String res = "false"; 309 Map<String, Serializable> props = getProperties(layoutMode, mode); 310 if (props != null && props.containsKey(REQUIRED_PROPERTY_NAME)) { 311 Object value = props.get(REQUIRED_PROPERTY_NAME); 312 if (value instanceof Boolean) { 313 res = value.toString(); 314 } else if (value instanceof String) { 315 res = (String) value; 316 } 317 } 318 return res; 319 } 320 321 @Override 322 public WidgetDefinition[] getSubWidgetDefinitions() { 323 return subWidgets; 324 } 325 326 @Override 327 public void setSubWidgetDefinitions(WidgetDefinition[] subWidgets) { 328 this.subWidgets = subWidgets; 329 } 330 331 @Override 332 public WidgetReference[] getSubWidgetReferences() { 333 return subWidgetReferences; 334 } 335 336 @Override 337 public void setSubWidgetReferences(WidgetReference[] subWidgetReferences) { 338 this.subWidgetReferences = subWidgetReferences; 339 } 340 341 @Override 342 public String getType() { 343 return type; 344 } 345 346 @Override 347 public void setType(String type) { 348 this.type = type; 349 } 350 351 @Override 352 public String getTypeCategory() { 353 return typeCategory; 354 } 355 356 @Override 357 public void setTypeCategory(String typeCategory) { 358 this.typeCategory = typeCategory; 359 } 360 361 @Override 362 public boolean isTranslated() { 363 return translated; 364 } 365 366 @Override 367 public void setTranslated(boolean translated) { 368 this.translated = translated; 369 } 370 371 @Override 372 public boolean isHandlingLabels() { 373 // migration code 374 Map<String, Serializable> controls = getControls(BuiltinModes.ANY, BuiltinModes.ANY); 375 if (controls != null && controls.containsKey("handleLabels")) { 376 Serializable handling = controls.get("handleLabels"); 377 if (handling != null) { 378 return Boolean.parseBoolean(handling.toString()); 379 } 380 } 381 return handlingLabels; 382 } 383 384 @Override 385 public void setHandlingLabels(boolean handlingLabels) { 386 this.handlingLabels = handlingLabels; 387 } 388 389 public static Map<String, Serializable> getProperties(Map<String, Map<String, Serializable>> properties, String mode) { 390 Map<String, Serializable> res = new HashMap<>(); 391 if (properties != null) { 392 Map<String, Serializable> propsInAnyMode = properties.get(BuiltinModes.ANY); 393 if (propsInAnyMode != null) { 394 res.putAll(propsInAnyMode); 395 } 396 Map<String, Serializable> propsInMode = properties.get(mode); 397 if (propsInMode != null) { 398 res.putAll(propsInMode); 399 } 400 } 401 return res; 402 } 403 404 @Override 405 public WidgetSelectOption[] getSelectOptions() { 406 return selectOptions; 407 } 408 409 @Override 410 public void setSelectOptions(WidgetSelectOption[] selectOptions) { 411 this.selectOptions = selectOptions; 412 } 413 414 @Override 415 public Map<String, List<RenderingInfo>> getRenderingInfos() { 416 return renderingInfos; 417 } 418 419 @Override 420 public void setRenderingInfos(Map<String, List<RenderingInfo>> renderingInfos) { 421 this.renderingInfos = renderingInfos; 422 } 423 424 public static List<RenderingInfo> getRenderingInfos(Map<String, List<RenderingInfo>> infos, String mode) { 425 List<RenderingInfo> res = new ArrayList<>(); 426 if (infos != null) { 427 List<RenderingInfo> inAnyMode = infos.get(BuiltinModes.ANY); 428 if (inAnyMode != null) { 429 res.addAll(inAnyMode); 430 } 431 List<RenderingInfo> inMode = infos.get(mode); 432 if (inMode != null) { 433 res.addAll(inMode); 434 } 435 } 436 return res; 437 } 438 439 @Override 440 public List<RenderingInfo> getRenderingInfos(String mode) { 441 return getRenderingInfos(renderingInfos, mode); 442 } 443 444 @Override 445 public boolean isDynamic() { 446 return dynamic; 447 } 448 449 public void setDynamic(boolean dynamic) { 450 this.dynamic = dynamic; 451 } 452 453 @Override 454 public boolean isGlobal() { 455 return global; 456 } 457 458 @Override 459 public void setGlobal(boolean global) { 460 this.global = global; 461 } 462 463 @Override 464 public List<String> getAliases() { 465 return aliases; 466 } 467 468 public void setAliases(List<String> aliases) { 469 this.aliases = aliases; 470 } 471 472 @Override 473 public WidgetDefinition clone() { 474 Map<String, Map<String, Serializable>> cprops = null; 475 if (properties != null) { 476 cprops = new HashMap<>(); 477 for (Map.Entry<String, Map<String, Serializable>> entry : properties.entrySet()) { 478 Map<String, Serializable> subProps = entry.getValue(); 479 Map<String, Serializable> csubProps = null; 480 if (subProps != null) { 481 csubProps = new HashMap<>(); 482 csubProps.putAll(subProps); 483 } 484 cprops.put(entry.getKey(), csubProps); 485 } 486 } 487 Map<String, Map<String, Serializable>> ccontrols = null; 488 if (controls != null) { 489 ccontrols = new HashMap<>(); 490 for (Map.Entry<String, Map<String, Serializable>> entry : controls.entrySet()) { 491 Map<String, Serializable> subControls = entry.getValue(); 492 Map<String, Serializable> csubControls = null; 493 if (subControls != null) { 494 csubControls = new HashMap<>(); 495 csubControls.putAll(subControls); 496 } 497 ccontrols.put(entry.getKey(), csubControls); 498 } 499 } 500 Map<String, String> clabels = null; 501 if (labels != null) { 502 clabels = new HashMap<>(); 503 clabels.putAll(labels); 504 } 505 Map<String, String> chelpLabels = null; 506 if (helpLabels != null) { 507 chelpLabels = new HashMap<>(); 508 chelpLabels.putAll(helpLabels); 509 } 510 Map<String, String> cmodes = null; 511 if (modes != null) { 512 cmodes = new HashMap<>(); 513 cmodes.putAll(modes); 514 } 515 FieldDefinition[] cfieldDefinitions = null; 516 if (fieldDefinitions != null) { 517 cfieldDefinitions = new FieldDefinition[fieldDefinitions.length]; 518 for (int i = 0; i < fieldDefinitions.length; i++) { 519 cfieldDefinitions[i] = fieldDefinitions[i].clone(); 520 } 521 } 522 Map<String, Map<String, Serializable>> cwidgetProps = null; 523 if (widgetModeProperties != null) { 524 cwidgetProps = new HashMap<>(); 525 for (Map.Entry<String, Map<String, Serializable>> entry : widgetModeProperties.entrySet()) { 526 Map<String, Serializable> subProps = entry.getValue(); 527 Map<String, Serializable> csubProps = null; 528 if (subProps != null) { 529 csubProps = new HashMap<>(); 530 csubProps.putAll(subProps); 531 } 532 cwidgetProps.put(entry.getKey(), csubProps); 533 } 534 } 535 WidgetDefinition[] csubWidgets = null; 536 if (subWidgets != null) { 537 csubWidgets = new WidgetDefinition[subWidgets.length]; 538 for (int i = 0; i < subWidgets.length; i++) { 539 csubWidgets[i] = subWidgets[i].clone(); 540 } 541 } 542 WidgetReference[] csubWidgetRefs = null; 543 if (subWidgetReferences != null) { 544 csubWidgetRefs = new WidgetReference[subWidgetReferences.length]; 545 for (int i = 0; i < subWidgetReferences.length; i++) { 546 csubWidgetRefs[i] = subWidgetReferences[i].clone(); 547 } 548 } 549 WidgetSelectOption[] cselectOptions = null; 550 if (selectOptions != null) { 551 cselectOptions = new WidgetSelectOption[selectOptions.length]; 552 for (int i = 0; i < selectOptions.length; i++) { 553 cselectOptions[i] = selectOptions[i].clone(); 554 } 555 } 556 Map<String, List<RenderingInfo>> crenderingInfos = null; 557 if (renderingInfos != null) { 558 crenderingInfos = new HashMap<>(); 559 for (Map.Entry<String, List<RenderingInfo>> item : renderingInfos.entrySet()) { 560 List<RenderingInfo> infos = item.getValue(); 561 List<RenderingInfo> clonedInfos = null; 562 if (infos != null) { 563 clonedInfos = new ArrayList<>(); 564 for (RenderingInfo info : infos) { 565 clonedInfos.add(info.clone()); 566 } 567 } 568 crenderingInfos.put(item.getKey(), clonedInfos); 569 } 570 } 571 WidgetDefinitionImpl clone = new WidgetDefinitionImpl(name, type, clabels, chelpLabels, translated, cmodes, 572 cfieldDefinitions, cprops, cwidgetProps, csubWidgets, cselectOptions); 573 clone.setTypeCategory(typeCategory); 574 clone.setRenderingInfos(crenderingInfos); 575 clone.setSubWidgetReferences(csubWidgetRefs); 576 clone.setHandlingLabels(handlingLabels); 577 clone.setControls(ccontrols); 578 if (aliases != null) { 579 clone.setAliases(new ArrayList<>(aliases)); 580 } 581 clone.setDynamic(dynamic); 582 clone.setGlobal(global); 583 return clone; 584 } 585 586 /** 587 * @since 7.2 588 */ 589 @Override 590 public boolean equals(Object obj) { 591 if (!(obj instanceof WidgetDefinitionImpl)) { 592 return false; 593 } 594 if (obj == this) { 595 return true; 596 } 597 WidgetDefinitionImpl w = (WidgetDefinitionImpl) obj; 598 return new EqualsBuilder().append(name, w.name).append(type, w.type).append(typeCategory, w.typeCategory).append( 599 labels, w.labels).append(helpLabels, w.helpLabels).append(translated, w.translated).append( 600 handlingLabels, w.handlingLabels).append(modes, w.modes).append(fieldDefinitions, w.fieldDefinitions).append( 601 properties, w.properties).append(widgetModeProperties, w.widgetModeProperties).append(controls, 602 w.controls).append(subWidgets, w.subWidgets).append(subWidgetReferences, w.subWidgetReferences).append( 603 selectOptions, w.selectOptions).append(renderingInfos, w.renderingInfos).append(aliases, w.aliases).append( 604 dynamic, w.dynamic).append(global, w.global).isEquals(); 605 } 606 607 /** 608 * @since 7.1 609 */ 610 @Override 611 public String toString() { 612 final StringBuilder sb = new StringBuilder(); 613 614 sb.append("WidgetDefinitionImpl"); 615 sb.append(" {"); 616 sb.append(" name="); 617 sb.append(name); 618 sb.append(", type="); 619 sb.append(type); 620 sb.append(", typeCategory="); 621 sb.append(typeCategory); 622 sb.append(", properties="); 623 sb.append(properties); 624 sb.append(", controls="); 625 sb.append(controls); 626 sb.append('}'); 627 628 return sb.toString(); 629 } 630 631}