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<String, String>(); 100 if (label != null) { 101 this.labels.put(BuiltinModes.ANY, label); 102 } 103 this.helpLabels = new HashMap<String, String>(); 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<String, Map<String, Serializable>>(); 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 public void setHelpLabels(Map<String, String> helpLabels) { 206 this.helpLabels = helpLabels; 207 } 208 209 @Override 210 public String getLabel(String mode) { 211 String label = labels.get(mode); 212 if (label == null) { 213 label = labels.get(BuiltinModes.ANY); 214 } 215 return label; 216 } 217 218 @Override 219 public Map<String, String> getLabels() { 220 return labels; 221 } 222 223 public void setLabels(Map<String, String> labels) { 224 this.labels = labels; 225 } 226 227 @Override 228 public String getMode(String layoutMode) { 229 if (modes != null) { 230 String mode = modes.get(layoutMode); 231 if (mode == null) { 232 mode = modes.get(BuiltinModes.ANY); 233 } 234 return mode; 235 } 236 return null; 237 } 238 239 @Override 240 public Map<String, String> getModes() { 241 return modes; 242 } 243 244 public void setModes(Map<String, String> modes) { 245 this.modes = modes; 246 } 247 248 @Override 249 public String getName() { 250 return name; 251 } 252 253 public void setName(String name) { 254 this.name = name; 255 } 256 257 @Override 258 public Map<String, Serializable> getProperties(String layoutMode, String mode) { 259 Map<String, Serializable> modeProps = getProperties(properties, layoutMode); 260 Map<String, Serializable> widgetModeProps = getProperties(widgetModeProperties, mode); 261 if (modeProps == null && widgetModeProps == null) { 262 return null; 263 } else if (widgetModeProps == null) { 264 return modeProps; 265 } else if (modeProps == null) { 266 return widgetModeProps; 267 } else { 268 // take mode values, and override with widget mode values 269 Map<String, Serializable> res = new HashMap<String, Serializable>(modeProps); 270 res.putAll(widgetModeProps); 271 return res; 272 } 273 } 274 275 @Override 276 public Map<String, Map<String, Serializable>> getProperties() { 277 return properties; 278 } 279 280 public void setProperties(Map<String, Map<String, Serializable>> properties) { 281 this.properties = properties; 282 } 283 284 @Override 285 public Map<String, Map<String, Serializable>> getWidgetModeProperties() { 286 return widgetModeProperties; 287 } 288 289 public void setWidgetModeProperties(Map<String, Map<String, Serializable>> widgetModeProperties) { 290 this.widgetModeProperties = widgetModeProperties; 291 } 292 293 @Override 294 public Map<String, Serializable> getControls(String layoutMode, String mode) { 295 return getProperties(controls, layoutMode); 296 } 297 298 @Override 299 public Map<String, Map<String, Serializable>> getControls() { 300 return controls; 301 } 302 303 @Override 304 public void setControls(Map<String, Map<String, Serializable>> controls) { 305 this.controls = controls; 306 } 307 308 @Override 309 public String getRequired(String layoutMode, String mode) { 310 String res = "false"; 311 Map<String, Serializable> props = getProperties(layoutMode, mode); 312 if (props != null && props.containsKey(REQUIRED_PROPERTY_NAME)) { 313 Object value = props.get(REQUIRED_PROPERTY_NAME); 314 if (value instanceof Boolean) { 315 res = value.toString(); 316 } else if (value instanceof String) { 317 res = (String) value; 318 } 319 } 320 return res; 321 } 322 323 @Override 324 public WidgetDefinition[] getSubWidgetDefinitions() { 325 return subWidgets; 326 } 327 328 public void setSubWidgetDefinitions(WidgetDefinition[] subWidgets) { 329 this.subWidgets = subWidgets; 330 } 331 332 public WidgetReference[] getSubWidgetReferences() { 333 return subWidgetReferences; 334 } 335 336 public void setSubWidgetReferences(WidgetReference[] subWidgetReferences) { 337 this.subWidgetReferences = subWidgetReferences; 338 } 339 340 @Override 341 public String getType() { 342 return type; 343 } 344 345 public void setType(String type) { 346 this.type = type; 347 } 348 349 public String getTypeCategory() { 350 return typeCategory; 351 } 352 353 public void setTypeCategory(String typeCategory) { 354 this.typeCategory = typeCategory; 355 } 356 357 @Override 358 public boolean isTranslated() { 359 return translated; 360 } 361 362 public void setTranslated(boolean translated) { 363 this.translated = translated; 364 } 365 366 public boolean isHandlingLabels() { 367 // migration code 368 Map<String, Serializable> controls = getControls(BuiltinModes.ANY, BuiltinModes.ANY); 369 if (controls != null && controls.containsKey("handleLabels")) { 370 Serializable handling = controls.get("handleLabels"); 371 if (handling != null) { 372 return Boolean.parseBoolean(handling.toString()); 373 } 374 } 375 return handlingLabels; 376 } 377 378 public void setHandlingLabels(boolean handlingLabels) { 379 this.handlingLabels = handlingLabels; 380 } 381 382 public static Map<String, Serializable> getProperties(Map<String, Map<String, Serializable>> properties, String mode) { 383 Map<String, Serializable> res = new HashMap<String, Serializable>(); 384 if (properties != null) { 385 Map<String, Serializable> propsInAnyMode = properties.get(BuiltinModes.ANY); 386 if (propsInAnyMode != null) { 387 res.putAll(propsInAnyMode); 388 } 389 Map<String, Serializable> propsInMode = properties.get(mode); 390 if (propsInMode != null) { 391 res.putAll(propsInMode); 392 } 393 } 394 return res; 395 } 396 397 @Override 398 public WidgetSelectOption[] getSelectOptions() { 399 return selectOptions; 400 } 401 402 public void setSelectOptions(WidgetSelectOption[] selectOptions) { 403 this.selectOptions = selectOptions; 404 } 405 406 @Override 407 public Map<String, List<RenderingInfo>> getRenderingInfos() { 408 return renderingInfos; 409 } 410 411 public void setRenderingInfos(Map<String, List<RenderingInfo>> renderingInfos) { 412 this.renderingInfos = renderingInfos; 413 } 414 415 public static List<RenderingInfo> getRenderingInfos(Map<String, List<RenderingInfo>> infos, String mode) { 416 List<RenderingInfo> res = new ArrayList<RenderingInfo>(); 417 if (infos != null) { 418 List<RenderingInfo> inAnyMode = infos.get(BuiltinModes.ANY); 419 if (inAnyMode != null) { 420 res.addAll(inAnyMode); 421 } 422 List<RenderingInfo> inMode = infos.get(mode); 423 if (inMode != null) { 424 res.addAll(inMode); 425 } 426 } 427 return res; 428 } 429 430 @Override 431 public List<RenderingInfo> getRenderingInfos(String mode) { 432 return getRenderingInfos(renderingInfos, mode); 433 } 434 435 public boolean isDynamic() { 436 return dynamic; 437 } 438 439 public void setDynamic(boolean dynamic) { 440 this.dynamic = dynamic; 441 } 442 443 public boolean isGlobal() { 444 return global; 445 } 446 447 public void setGlobal(boolean global) { 448 this.global = global; 449 } 450 451 @Override 452 public List<String> getAliases() { 453 return aliases; 454 } 455 456 public void setAliases(List<String> aliases) { 457 this.aliases = aliases; 458 } 459 460 @Override 461 public WidgetDefinition clone() { 462 Map<String, Map<String, Serializable>> cprops = null; 463 if (properties != null) { 464 cprops = new HashMap<String, Map<String, Serializable>>(); 465 for (Map.Entry<String, Map<String, Serializable>> entry : properties.entrySet()) { 466 Map<String, Serializable> subProps = entry.getValue(); 467 Map<String, Serializable> csubProps = null; 468 if (subProps != null) { 469 csubProps = new HashMap<String, Serializable>(); 470 csubProps.putAll(subProps); 471 } 472 cprops.put(entry.getKey(), csubProps); 473 } 474 } 475 Map<String, Map<String, Serializable>> ccontrols = null; 476 if (controls != null) { 477 ccontrols = new HashMap<String, Map<String, Serializable>>(); 478 for (Map.Entry<String, Map<String, Serializable>> entry : controls.entrySet()) { 479 Map<String, Serializable> subControls = entry.getValue(); 480 Map<String, Serializable> csubControls = null; 481 if (subControls != null) { 482 csubControls = new HashMap<String, Serializable>(); 483 csubControls.putAll(subControls); 484 } 485 ccontrols.put(entry.getKey(), csubControls); 486 } 487 } 488 Map<String, String> clabels = null; 489 if (labels != null) { 490 clabels = new HashMap<String, String>(); 491 clabels.putAll(labels); 492 } 493 Map<String, String> chelpLabels = null; 494 if (helpLabels != null) { 495 chelpLabels = new HashMap<String, String>(); 496 chelpLabels.putAll(helpLabels); 497 } 498 Map<String, String> cmodes = null; 499 if (modes != null) { 500 cmodes = new HashMap<String, String>(); 501 cmodes.putAll(modes); 502 } 503 FieldDefinition[] cfieldDefinitions = null; 504 if (fieldDefinitions != null) { 505 cfieldDefinitions = new FieldDefinition[fieldDefinitions.length]; 506 for (int i = 0; i < fieldDefinitions.length; i++) { 507 cfieldDefinitions[i] = fieldDefinitions[i].clone(); 508 } 509 } 510 Map<String, Map<String, Serializable>> cwidgetProps = null; 511 if (widgetModeProperties != null) { 512 cwidgetProps = new HashMap<String, Map<String, Serializable>>(); 513 for (Map.Entry<String, Map<String, Serializable>> entry : widgetModeProperties.entrySet()) { 514 Map<String, Serializable> subProps = entry.getValue(); 515 Map<String, Serializable> csubProps = null; 516 if (subProps != null) { 517 csubProps = new HashMap<String, Serializable>(); 518 csubProps.putAll(subProps); 519 } 520 cwidgetProps.put(entry.getKey(), csubProps); 521 } 522 } 523 WidgetDefinition[] csubWidgets = null; 524 if (subWidgets != null) { 525 csubWidgets = new WidgetDefinition[subWidgets.length]; 526 for (int i = 0; i < subWidgets.length; i++) { 527 csubWidgets[i] = subWidgets[i].clone(); 528 } 529 } 530 WidgetReference[] csubWidgetRefs = null; 531 if (subWidgetReferences != null) { 532 csubWidgetRefs = new WidgetReference[subWidgetReferences.length]; 533 for (int i = 0; i < subWidgetReferences.length; i++) { 534 csubWidgetRefs[i] = subWidgetReferences[i].clone(); 535 } 536 } 537 WidgetSelectOption[] cselectOptions = null; 538 if (selectOptions != null) { 539 cselectOptions = new WidgetSelectOption[selectOptions.length]; 540 for (int i = 0; i < selectOptions.length; i++) { 541 cselectOptions[i] = selectOptions[i].clone(); 542 } 543 } 544 Map<String, List<RenderingInfo>> crenderingInfos = null; 545 if (renderingInfos != null) { 546 crenderingInfos = new HashMap<String, List<RenderingInfo>>(); 547 for (Map.Entry<String, List<RenderingInfo>> item : renderingInfos.entrySet()) { 548 List<RenderingInfo> infos = item.getValue(); 549 List<RenderingInfo> clonedInfos = null; 550 if (infos != null) { 551 clonedInfos = new ArrayList<RenderingInfo>(); 552 for (RenderingInfo info : infos) { 553 clonedInfos.add(info.clone()); 554 } 555 } 556 crenderingInfos.put(item.getKey(), clonedInfos); 557 } 558 } 559 WidgetDefinitionImpl clone = new WidgetDefinitionImpl(name, type, clabels, chelpLabels, translated, cmodes, 560 cfieldDefinitions, cprops, cwidgetProps, csubWidgets, cselectOptions); 561 clone.setTypeCategory(typeCategory); 562 clone.setRenderingInfos(crenderingInfos); 563 clone.setSubWidgetReferences(csubWidgetRefs); 564 clone.setHandlingLabels(handlingLabels); 565 clone.setControls(ccontrols); 566 if (aliases != null) { 567 clone.setAliases(new ArrayList<String>(aliases)); 568 } 569 clone.setDynamic(dynamic); 570 clone.setGlobal(global); 571 return clone; 572 } 573 574 /** 575 * @since 7.2 576 */ 577 @Override 578 public boolean equals(Object obj) { 579 if (!(obj instanceof WidgetDefinitionImpl)) { 580 return false; 581 } 582 if (obj == this) { 583 return true; 584 } 585 WidgetDefinitionImpl w = (WidgetDefinitionImpl) obj; 586 return new EqualsBuilder().append(name, w.name).append(type, w.type).append(typeCategory, w.typeCategory).append( 587 labels, w.labels).append(helpLabels, w.helpLabels).append(translated, w.translated).append( 588 handlingLabels, w.handlingLabels).append(modes, w.modes).append(fieldDefinitions, w.fieldDefinitions).append( 589 properties, w.properties).append(widgetModeProperties, w.widgetModeProperties).append(controls, 590 w.controls).append(subWidgets, w.subWidgets).append(subWidgetReferences, w.subWidgetReferences).append( 591 selectOptions, w.selectOptions).append(renderingInfos, w.renderingInfos).append(aliases, w.aliases).append( 592 dynamic, w.dynamic).append(global, w.global).isEquals(); 593 } 594 595 /** 596 * @since 7.1 597 */ 598 @Override 599 public String toString() { 600 final StringBuilder buf = new StringBuilder(); 601 602 buf.append("WidgetDefinitionImpl"); 603 buf.append(" {"); 604 buf.append(" name="); 605 buf.append(name); 606 buf.append(", type="); 607 buf.append(type); 608 buf.append(", typeCategory="); 609 buf.append(typeCategory); 610 buf.append(", properties="); 611 buf.append(properties); 612 buf.append(", controls="); 613 buf.append(controls); 614 buf.append('}'); 615 616 return buf.toString(); 617 } 618 619}