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