001/* 002 * Copyright 2018 Anyware Services 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 */ 016package org.ametys.plugins.contenttypeseditor; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Map.Entry; 025import java.util.Optional; 026 027import org.apache.avalon.framework.component.Component; 028import org.apache.avalon.framework.configuration.Configuration; 029import org.apache.avalon.framework.configuration.ConfigurationException; 030import org.apache.avalon.framework.configuration.DefaultConfigurationSerializer; 031import org.apache.avalon.framework.logger.AbstractLogEnabled; 032import org.apache.avalon.framework.service.ServiceException; 033import org.apache.avalon.framework.service.ServiceManager; 034import org.apache.avalon.framework.service.Serviceable; 035import org.apache.commons.lang.StringUtils; 036import org.xml.sax.SAXException; 037 038import org.ametys.cms.contenttype.ContentAttributeDefinition; 039import org.ametys.cms.contenttype.ContentType; 040import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 041import org.ametys.cms.contenttype.RichTextAttributeDefinition; 042import org.ametys.cms.contenttype.SemanticAnnotation; 043import org.ametys.cms.contenttype.indexing.CustomIndexingField; 044import org.ametys.cms.contenttype.indexing.IndexingField; 045import org.ametys.cms.contenttype.indexing.IndexingModel; 046import org.ametys.cms.contenttype.indexing.MetadataIndexingField; 047import org.ametys.cms.languages.Language; 048import org.ametys.cms.languages.LanguagesManager; 049import org.ametys.core.right.Right; 050import org.ametys.core.right.RightsExtensionPoint; 051import org.ametys.core.util.I18nUtils; 052import org.ametys.plugins.repository.model.CompositeDefinition; 053import org.ametys.plugins.repository.model.RepeaterDefinition; 054import org.ametys.runtime.i18n.I18nizableText; 055import org.ametys.runtime.model.ElementDefinition; 056import org.ametys.runtime.model.Enumerator; 057import org.ametys.runtime.model.Model; 058import org.ametys.runtime.model.ModelItem; 059import org.ametys.runtime.model.ModelItemGroup; 060import org.ametys.runtime.model.ModelViewItem; 061import org.ametys.runtime.model.SimpleViewItemGroup; 062import org.ametys.runtime.model.StaticEnumerator; 063import org.ametys.runtime.model.View; 064import org.ametys.runtime.model.ViewItem; 065import org.ametys.runtime.model.ViewItemContainer; 066import org.ametys.runtime.parameter.DefaultValidator; 067import org.ametys.runtime.parameter.Validator; 068import org.ametys.runtime.plugin.component.PluginAware; 069 070/** 071 * Helper to retrieve content type infos 072 */ 073public class ContentTypeInformationsHelper extends AbstractLogEnabled implements Component, Serviceable, PluginAware 074{ 075 /** The Avalon role name */ 076 public static final String ROLE = ContentTypeInformationsHelper.class.getName(); 077 078 /** The content type extension point instance */ 079 protected ContentTypeExtensionPoint _contentTypeExtensionPoint; 080 081 /** The rights extension point instance */ 082 protected RightsExtensionPoint _rightsExtensionPoint; 083 084 /** Utility methods helping the management of internationalizable text */ 085 protected I18nUtils _i18nUtils; 086 087 /** The langage manager instance */ 088 protected LanguagesManager _langageManager; 089 090 Map<String, Language> _availableLanguages; 091 092 private String _pluginName; 093 094 /** 095 * Enumeration of metadata type 096 */ 097 public enum ContentTypeAttributeDataType 098 { 099 /** Metadata type */ 100 METADATA, 101 102 /** Metadata set type */ 103 METADATA_SET, 104 105 /** Fieldset type */ 106 FIELDSET, 107 108 /** Metadata reference type */ 109 METADATA_REF, 110 111 /** Indexing field type */ 112 INDEXING_FIELD 113 } 114 115 @Override 116 public void service(ServiceManager serviceManager) throws ServiceException 117 { 118 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 119 _rightsExtensionPoint = (RightsExtensionPoint) serviceManager.lookup(RightsExtensionPoint.ROLE); 120 _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE); 121 _langageManager = (LanguagesManager) serviceManager.lookup(LanguagesManager.ROLE); 122 _availableLanguages = _langageManager.getAvailableLanguages(); 123 } 124 125 public void setPluginInfo(String pluginName, String featureName, String id) 126 { 127 _pluginName = pluginName; 128 } 129 130 /** 131 * Retrieves content type information 132 * @param contentTypeId the content type's identifier 133 * @param hideInheritedModelItems <code>true</code> to hide inherited model items of a content type according to contentTypeId parameter 134 * @param resolveMultilingualString if <code>true</code>, the multilingual string will be returned as simple strings 135 * @return a <code>Map</code> containing all information about the content type 136 */ 137 public Map<String, Object> getContentTypeInfos(String contentTypeId, boolean hideInheritedModelItems, boolean resolveMultilingualString) 138 { 139 ContentType cType = _contentTypeExtensionPoint.getExtension(contentTypeId); 140 if (cType == null) 141 { 142 throw new IllegalStateException("Unknown content type '" + contentTypeId + "'"); 143 } 144 145 Map<String, Object> contentTypeInfos = new HashMap<>(); 146 147 contentTypeInfos.put("id", cType.getId()); 148 contentTypeInfos.put("label", getEnhancedMultilingualString(cType.getLabel(), resolveMultilingualString)); 149 contentTypeInfos.put("description", getEnhancedMultilingualString(cType.getDescription(), resolveMultilingualString)); 150 151 contentTypeInfos.put("iconGlyph", cType.getIconGlyph()); 152 contentTypeInfos.put("iconDecorator", cType.getIconDecorator()); 153 contentTypeInfos.put("largeIcon", cType.getLargeIcon()); 154 contentTypeInfos.put("mediumIcon", cType.getMediumIcon()); 155 contentTypeInfos.put("smallIcon", cType.getSmallIcon()); 156 157 contentTypeInfos.put("hasImages", _hasImages(cType)); 158 contentTypeInfos.put("category", getEnhancedMultilingualString(cType.getCategory(), resolveMultilingualString)); 159 contentTypeInfos.put("pluginName", cType.getPluginName()); 160 contentTypeInfos.put("defaultTitle", getEnhancedMultilingualString(cType.getDefaultTitle(), resolveMultilingualString)); 161 162 I18nizableText rightLabel = _getRightLabel(cType.getRight()); 163 if (rightLabel != null) 164 { 165 contentTypeInfos.put("right", _getTextForAvailableLanguages(rightLabel, false)); 166 } 167 168 contentTypeInfos.put("private", cType.isPrivate()); 169 contentTypeInfos.put("abstract", cType.isAbstract()); 170 contentTypeInfos.put("multilingual", cType.isMultilingual()); 171 contentTypeInfos.put("mixin", cType.isMixin()); 172 contentTypeInfos.put("referencetable", cType.isReferenceTable()); 173 contentTypeInfos.put("simple", cType.isSimple()); 174 175 contentTypeInfos.put("superTypes", _getSuperTypesInfos(cType)); 176 cType.getParentAttributeDefinition().ifPresent(definition -> contentTypeInfos.put("parentRef", definition.getName())); 177 178 contentTypeInfos.put("metadataNames", _getAttributeNames(cType.getModelItems())); 179 contentTypeInfos.put("attributes", getModelItemsInformation(cType, hideInheritedModelItems, resolveMultilingualString)); 180 contentTypeInfos.put("views", _getViews(cType, hideInheritedModelItems, resolveMultilingualString)); 181 182 contentTypeInfos.put("indexingModel", _getIndexingModel(cType)); 183 184 return contentTypeInfos; 185 } 186 187 private boolean _hasImages(ContentType contentType) 188 { 189 boolean hasImages = !contentType.getSmallIcon().endsWith("/unknown-small.png") || !contentType.getMediumIcon().endsWith("/unknown-medium.png") || !contentType.getLargeIcon().endsWith("/unknown-large.png"); 190 191 return hasImages; 192 } 193 194 private I18nizableText _getRightLabel(String rightId) 195 { 196 Right right = _rightsExtensionPoint.getExtension(rightId); 197 if (right != null) 198 { 199 return right.getLabel(); 200 } 201 return null; 202 } 203 204 private List<Map<String, Object>> _getSuperTypesInfos(ContentType cType) 205 { 206 List<Map<String, Object>> superTypesInfos = new ArrayList<>(); 207 for (String superTypeId : cType.getSupertypeIds()) 208 { 209 Map<String, Object> superTypeInfos = new HashMap<>(); 210 ContentType superType = _contentTypeExtensionPoint.getExtension(superTypeId); 211 superTypeInfos.put("id", superTypeId); 212 superTypeInfos.put("label", superType.getLabel()); 213 superTypeInfos.put("isMixin", superType.isMixin()); 214 superTypesInfos.add(superTypeInfos); 215 216 } 217 return superTypesInfos; 218 } 219 220 private Collection<String> _getAttributeNames(Collection<? extends ModelItem> modelItems) 221 { 222 Collection<String> attributeNames = new HashSet<>(); 223 224 for (ModelItem modelItem : modelItems) 225 { 226 attributeNames.add(modelItem.getName()); 227 if (modelItem instanceof ModelItemGroup) 228 { 229 attributeNames.addAll(_getAttributeNames(((ModelItemGroup) modelItem).getModelItems())); 230 } 231 } 232 233 return attributeNames; 234 } 235 236 /** 237 * Get model items' information of a content type 238 * @param contentType The content type 239 * @param hideInheritedModelItems <code>true</code> to hide inherited mode items of content type 240 * @param resolveMultilingualString If <code>true</code>, the multilingual string will be returned as simple strings 241 * @return Model items' information of a content type 242 */ 243 public List<Map<String, Object>> getModelItemsInformation(ContentType contentType, boolean hideInheritedModelItems, boolean resolveMultilingualString) 244 { 245 List<Map<String, Object>> modelItems = new ArrayList<>(); 246 for (ModelItem modelItem : contentType.getModelItems()) 247 { 248 Model model = modelItem.getModel(); 249 if (hideInheritedModelItems) 250 { 251 if (model.equals(contentType)) 252 { 253 modelItems.add(_getModelItemValues(contentType, modelItem, resolveMultilingualString)); 254 } 255 } 256 else 257 { 258 modelItems.add(_getModelItemValues(contentType, modelItem, resolveMultilingualString)); 259 } 260 } 261 return modelItems; 262 } 263 264 private Map<String, Object> _getModelItemValues(ContentType contentType, ModelItem modelItem, boolean resolveMultilingualString) 265 { 266 Map<String, Object> values = new HashMap<>(); 267 268 values.put("dataType", ContentTypeAttributeDataType.METADATA.name().toLowerCase()); 269 270 values.put("label", getEnhancedMultilingualString(modelItem.getLabel(), resolveMultilingualString)); 271 values.put("description", getEnhancedMultilingualString(modelItem.getDescription(), resolveMultilingualString)); 272 273 values.put("name", modelItem.getName()); 274 values.put("path", modelItem.getPath()); 275 values.put("type", modelItem.getType().getId()); 276 277 values.put("contentTypeId", contentType.getId()); 278 ContentType referenceContentType = (ContentType) modelItem.getModel(); 279 values.put("referenceContentTypeId", referenceContentType.getId()); 280 values.put("referenceContentTypeLabel", referenceContentType.getLabel()); 281 values.put("isParentMetadata", !referenceContentType.equals(contentType)); 282 283 if (modelItem instanceof ElementDefinition) 284 { 285 values.putAll(_getElementDefinitionValues((ElementDefinition) modelItem, resolveMultilingualString)); 286 } 287 else if (modelItem instanceof RepeaterDefinition) 288 { 289 values.putAll(_getRepeaterValues((RepeaterDefinition) modelItem, resolveMultilingualString)); 290 } 291 292 if (modelItem instanceof ModelItemGroup) 293 { 294 values.put("leaf", false); 295 296 List<Map<String, Object>> children = new ArrayList<>(); 297 for (ModelItem child : ((ModelItemGroup) modelItem).getModelItems()) 298 { 299 children.add(_getModelItemValues(contentType, child, resolveMultilingualString)); 300 } 301 values.put("children", children); 302 } 303 else 304 { 305 values.put("leaf", true); 306 } 307 308 return values; 309 } 310 311 private Map<String, Object> _getElementDefinitionValues(ElementDefinition definition, boolean resolveMultilingualString) 312 { 313 Map<String, Object> values = new HashMap<>(); 314 315 values.put("pluginName", definition.getPluginName()); 316 317 values.put("defaultValue", definition.getDefaultValue()); 318 values.put("multiple", definition.isMultiple()); 319 320 values.put("widget", definition.getWidget()); 321 values.put("widgetParams", _getWidgetParameters(definition, resolveMultilingualString)); 322 323 values.put("enumerated", definition.getEnumerator() != null); 324 if (definition.getEnumerator() != null) 325 { 326 Enumerator enumerator = definition.getEnumerator(); 327 if (enumerator instanceof StaticEnumerator) 328 { 329 // Default enumerator 330 values.put("defaultEnumerator", _getEnhancedEnumerators(definition)); 331 } 332 else 333 { 334 // Custom enumerator 335 values.put("customEnumeratorClass", enumerator.getClass().getName()); 336 values.put("customEnumeratorConfiguration", _getConfiguration(definition.getEnumeratorConfiguration())); 337 } 338 } 339 340 values.put("validator", definition.getValidator() != null); 341 values.put("mandatory", _isMandatoryElementDefinition(definition)); 342 Validator validator = definition.getValidator(); 343 if (validator != null) 344 { 345 if (validator.getClass().equals(DefaultValidator.class)) 346 { 347 // Default validator 348 values.put("defaultValidator", _getValidatorParameters(definition, resolveMultilingualString)); 349 } 350 else 351 { 352 // Custom validator 353 values.put("customValidatorClass", validator.getClass().getName()); 354 values.put("customValidatorConfiguration", _getConfiguration(definition.getValidatorConfiguration())); 355 } 356 } 357 358 if (definition instanceof RichTextAttributeDefinition) 359 { 360 values.putAll(_getRichTextValues((RichTextAttributeDefinition) definition)); 361 } 362 else if (definition instanceof ContentAttributeDefinition) 363 { 364 values.putAll(_getContentValues((ContentAttributeDefinition) definition)); 365 } 366 367 return values; 368 } 369 370 private List<Map<String, Object>> _getWidgetParameters(ElementDefinition definition, boolean resolveMultilingualString) 371 { 372 List<Map<String, Object>> widgetParameters = new ArrayList<>(); 373 374 Map<String, I18nizableText> widgetParams = definition.getWidgetParameters(); 375 if (widgetParams != null) 376 { 377 for (Entry<String, I18nizableText> widgetParam : widgetParams.entrySet()) 378 { 379 Map<String, Object> params = new HashMap<>(); 380 params.put("label", widgetParam.getKey()); 381 params.put("value", getEnhancedMultilingualString(widgetParam.getValue(), resolveMultilingualString)); 382 widgetParameters.add(params); 383 } 384 } 385 return widgetParameters; 386 } 387 388 private List<Map<String, Object>> _getEnhancedEnumerators(ElementDefinition definition) 389 { 390 List<Map<String, Object>> enhancedEnumerators = new ArrayList<>(); 391 Enumerator enumerator = definition.getEnumerator(); 392 try 393 { 394 Map<Object, I18nizableText> entries = enumerator.getTypedEntries(); 395 for (Entry<Object, I18nizableText> entry : entries.entrySet()) 396 { 397 I18nizableText enumeratorLabel = entry.getValue(); 398 Map<String, Object> enhancedEnumerator = new HashMap<>(); 399 enhancedEnumerator.put("label", entry.getKey().toString()); 400 401 Map<String, Object> value = new HashMap<>(); 402 value.put("isMultilingual", enumeratorLabel.isI18n()); 403 if (enumeratorLabel.isI18n()) 404 { 405 value.put("values", _getTextForAvailableLanguages(enumeratorLabel, false)); 406 } 407 else 408 { 409 value.put("values", enumeratorLabel.getLabel()); 410 } 411 enhancedEnumerator.put("value", value); 412 enhancedEnumerators.add(enhancedEnumerator); 413 } 414 } 415 catch (Exception e) 416 { 417 getLogger().error("Unable to set values for enumerator " + enumerator.getClass().getName(), e); 418 } 419 return enhancedEnumerators; 420 } 421 422 private boolean _isMandatoryElementDefinition(ElementDefinition definition) 423 { 424 boolean isMandatory = false; 425 Validator validator = definition.getValidator(); 426 if (validator != null) 427 { 428 Map<String, Object> configuration = validator.getConfiguration(); 429 if (configuration != null) 430 { 431 Object object = configuration.get("mandatory"); 432 if (object instanceof Boolean) 433 { 434 isMandatory = (boolean) object; 435 } 436 } 437 } 438 return isMandatory; 439 } 440 441 private Map<String, Object> _getValidatorParameters(ElementDefinition definition, boolean resolveMultilingualString) 442 { 443 Map<String, Object> validatorParameters = new HashMap<>(); 444 Validator validator = definition.getValidator(); 445 Map<String, Object> configuration = validator.getConfiguration(); 446 Object mandatory = configuration.get("mandatory"); 447 if (mandatory.toString().equals("true")) 448 { 449 validatorParameters.put("mandatory", true); 450 } 451 Object regexp = configuration.get("regexp"); 452 if (regexp != null) 453 { 454 validatorParameters.put("regexp", regexp.toString()); 455 } 456 Object invalidText = configuration.get("invalidText"); 457 if (invalidText != null) 458 { 459 validatorParameters.put("invalidText", getEnhancedMultilingualString((I18nizableText) invalidText, resolveMultilingualString)); 460 } 461 return validatorParameters; 462 } 463 464 private String _getConfiguration(Configuration configuration) 465 { 466 String config = ""; 467 try 468 { 469 if (configuration != null) 470 { 471 DefaultConfigurationSerializer defaultConfigurationSerializer = new DefaultConfigurationSerializer(); 472 config = defaultConfigurationSerializer.serialize(configuration); 473 } 474 } 475 catch (ConfigurationException | SAXException e) 476 { 477 // Ignore 478 } 479 return config; 480 } 481 482 private Map<String, Object> _getRichTextValues(RichTextAttributeDefinition definition) 483 { 484 // TODO manage transformer and richTextOutgoingReferenceExtractor 485 Map<String, Object> values = new HashMap<>(); 486 487 List<SemanticAnnotation> annotations = definition.getSemanticAnnotations(); 488 List<Object> annotationsValues = new ArrayList<>(); 489 for (SemanticAnnotation annotation : annotations) 490 { 491 Map<String, Object> annotationValues = new HashMap<>(); 492 annotationValues.put("id", annotation.getId()); 493 annotationValues.put("label", annotation.getLabel()); 494 annotationValues.put("description", annotation.getDescription()); 495 annotationsValues.add(annotationValues); 496 } 497 values.put("semanticAnnotations", annotationsValues); 498 499 return values; 500 } 501 502 private Map<String, Object> _getContentValues(ContentAttributeDefinition definition) 503 { 504 Map<String, Object> values = new HashMap<>(); 505 506 String linkedContentTypeId = definition.getContentTypeId(); 507 if (linkedContentTypeId != null) 508 { 509 Map<String, Object> linkedCTypeInfos = new HashMap<>(); 510 linkedCTypeInfos.put("id", linkedContentTypeId); 511 512 ContentType linkedCType = _contentTypeExtensionPoint.getExtension(linkedContentTypeId); 513 linkedCTypeInfos.put("label", linkedCType.getLabel()); 514 linkedCTypeInfos.put("iconGlyph", linkedCType.getIconGlyph()); 515 516 values.put("linkedContentType", linkedCTypeInfos); 517 } 518 519 values.put("invertRelationPath", definition.getInvertRelationPath()); 520 values.put("forceInvert", definition.getForceInvert()); 521 522 return values; 523 } 524 525 private Map<String, Object> _getRepeaterValues(RepeaterDefinition definition, boolean resolveMultilingualString) 526 { 527 Map<String, Object> values = new HashMap<>(); 528 529 values.put("initializeSize", definition.getInitialSize()); 530 values.put("minSize", definition.getMinSize()); 531 values.put("maxSize", definition.getMaxSize()); 532 533 values.put("addLabel", getEnhancedMultilingualString(definition.getAddLabel(), resolveMultilingualString)); 534 values.put("deleteLabel", getEnhancedMultilingualString(definition.getDeleteLabel(), resolveMultilingualString)); 535 values.put("headerLabel", definition.getHeaderLabel()); 536 537 return values; 538 } 539 540 private List<Map<String, Object>> _getViews(ContentType contentType, boolean hideInheritedModelItems, boolean resolveMultilingualString) 541 { 542 List<Map<String, Object>> views = new ArrayList<>(); 543 for (String name : contentType.getViewNames()) 544 { 545 View view = contentType.getView(name); 546 views.add(_getViewValues(contentType, view, hideInheritedModelItems, resolveMultilingualString)); 547 } 548 return views; 549 } 550 551 private Map<String, Object> _getViewValues(ContentType contentType, View view, boolean hideInheritedModelItems, boolean resolveMultilingualString) 552 { 553 Map<String, Object> values = new HashMap<>(); 554 values.put("dataType", ContentTypeAttributeDataType.METADATA_SET.name().toLowerCase()); 555 556 values.put("name", view.getName()); 557 values.put("label", getEnhancedMultilingualString(view.getLabel(), resolveMultilingualString)); 558 values.put("description", getEnhancedMultilingualString(view.getDescription(), resolveMultilingualString)); 559 values.put("isInternal", view.isInternal()); 560 561 values.put("iconGlyph", view.getIconGlyph()); 562 values.put("iconDecorator", view.getIconDecorator()); 563 values.put("smallIcon", view.getSmallIcon()); 564 values.put("mediumIcon", view.getMediumIcon()); 565 values.put("largeIcon", view.getLargeIcon()); 566 if (!view.getIconGlyph().isEmpty()) 567 { 568 values.put("iconCls", view.getIconGlyph()); 569 } 570 else 571 { 572 values.put("icon", view.getSmallIcon()); 573 } 574 575 values.putAll(_processViewItemContainerChildren(contentType, view, hideInheritedModelItems, resolveMultilingualString)); 576 577 return values; 578 } 579 580 private Map<String, Object> _processViewItemContainerChildren(ContentType contentType, ViewItemContainer viewItemContainer, boolean hideInheritedModelItems, boolean resolveMultilingualString) 581 { 582 Map<String, Object> values = new HashMap<>(); 583 584 List<Map<String, Object>> children = new ArrayList<>(); 585 for (ViewItem viewItem : viewItemContainer.getViewItems()) 586 { 587 if (viewItem instanceof SimpleViewItemGroup) 588 { 589 children.add(_getSimpleViewItemGroupValues(contentType, (SimpleViewItemGroup) viewItem, hideInheritedModelItems, resolveMultilingualString)); 590 } 591 else if (viewItem instanceof ModelViewItem) 592 { 593 ModelItem modelItem = ((ModelViewItem) viewItem).getDefinition(); 594 if ((hideInheritedModelItems && contentType.equals(modelItem.getModel())) || !hideInheritedModelItems) 595 { 596 children.add(_getModelViewItemValues(contentType, (ModelViewItem) viewItem, hideInheritedModelItems, resolveMultilingualString)); 597 } 598 } 599 } 600 601 values.put("leaf", children.isEmpty()); 602 values.put("children", children); 603 604 return values; 605 } 606 607 private Map<String, Object> _getSimpleViewItemGroupValues(ContentType contentType, SimpleViewItemGroup fieldset, boolean hideInheritedModelItems, boolean resolveMultilingualString) 608 { 609 Map<String, Object> values = new HashMap<>(); 610 values.put("dataType", ContentTypeAttributeDataType.FIELDSET.name().toLowerCase()); 611 612 values.put("label", getEnhancedMultilingualString(fieldset.getLabel(), resolveMultilingualString)); 613 values.put("role", fieldset.getRole()); 614 615 values.putAll(_processViewItemContainerChildren(contentType, fieldset, hideInheritedModelItems, resolveMultilingualString)); 616 617 return values; 618 } 619 620 private Map<String, Object> _getModelViewItemValues(ContentType contentType, ModelViewItem modelViewItem, boolean hideInheritedModelItems, boolean resolveMultilingualString) 621 { 622 Map<String, Object> values = new HashMap<>(); 623 624 values.put("dataType", ContentTypeAttributeDataType.METADATA_REF.name().toLowerCase()); 625 626 ModelItem modelItem = modelViewItem.getDefinition(); 627 values.put("label", getEnhancedMultilingualString(modelItem.getLabel(), resolveMultilingualString)); 628 values.put("name", modelItem.getName()); 629 values.put("path", modelItem.getPath()); 630 631 boolean isParentView = Optional.ofNullable(modelItem).map(item -> !contentType.equals(item.getModel())).orElse(true); 632 values.put("isParentMetadataSet", isParentView); 633 634 values.put("isRepeaterOrComposite", modelItem instanceof RepeaterDefinition || modelItem instanceof CompositeDefinition); 635 636 if (modelViewItem instanceof ViewItemContainer) 637 { 638 values.putAll(_processViewItemContainerChildren(contentType, (ViewItemContainer) modelViewItem, hideInheritedModelItems, resolveMultilingualString)); 639 } 640 else 641 { 642 values.put("leaf", true); 643 } 644 645 return values; 646 } 647 648 private List<Map<String, Object>> _getIndexingModel(ContentType cType) 649 { 650 List<Map<String, Object>> result = new ArrayList<>(); 651 IndexingModel indexingModel = cType.getIndexingModel(); 652 Collection<IndexingField> fields = indexingModel.getFields(); 653 for (IndexingField indexingField : fields) 654 { 655 result.add(_getIndexingFieldDetails(indexingField)); 656 } 657 return result; 658 } 659 660 private List<String> _getIndexingFieldPath(IndexingField indexingField) 661 { 662 List<String> indexingFieldPath = new ArrayList<>(); 663 if (indexingField instanceof CustomIndexingField) 664 { 665 indexingFieldPath = null; 666 } 667 else if (indexingField instanceof MetadataIndexingField) 668 { 669 MetadataIndexingField metadataIndexingField = (MetadataIndexingField) indexingField; 670 String metadataPath = metadataIndexingField.getMetadataPath(); 671 indexingFieldPath.add(metadataPath); 672 } 673 return indexingFieldPath; 674 } 675 676 private I18nizableText _getIndexingFieldType(IndexingField indexingField) 677 { 678 I18nizableText type = new I18nizableText("plugin." + _pluginName, "PLUGINS_CONTENTTYPESEDITOR_EDITOR_TOOL_INDEXING_MODEL_METADATA_TYPE"); 679 if (indexingField instanceof CustomIndexingField) 680 { 681 type = new I18nizableText("plugin." + _pluginName, "PLUGINS_CONTENTTYPESEDITOR_EDITOR_TOOL_INDEXING_MODEL_CUSTOM_METADATA_TYPE"); 682 } 683 return type; 684 } 685 686 private Map<String, Object> _getIndexingFieldDetails(IndexingField indexingField) 687 { 688 Map<String, Object> values = new HashMap<>(); 689 values.put("label", indexingField.getLabel()); 690 values.put("name", indexingField.getName()); 691 values.put("description", indexingField.getDescription()); 692 values.put("dataType", ContentTypeAttributeDataType.INDEXING_FIELD.name().toLowerCase()); 693 694 List<String> paths = _getIndexingFieldPath(indexingField); 695 values.put("path", paths); 696 if (indexingField instanceof CustomIndexingField) 697 { 698 values.put("class", indexingField.getClass()); 699 } 700 I18nizableText type = _getIndexingFieldType(indexingField); 701 values.put("type", type); 702 values.put("leaf", true); 703 return values; 704 } 705 706 /** 707 * Get values in different language of an i18n text 708 * @param text An i18n text 709 * @param resolveMultilingualString When true return a text 710 * @return values in different language of an i18n text 711 */ 712 public Object getEnhancedMultilingualString(I18nizableText text, boolean resolveMultilingualString) 713 { 714 if (resolveMultilingualString) 715 { 716 return text; 717 } 718 else 719 { 720 Map<String, Object> translatedText = new HashMap<>(); 721 if (text != null) 722 { 723 if (text.isI18n()) 724 { 725 Map<String, String> textForAvailableLanguages = _getTextForAvailableLanguages(text, false); 726 if (!textForAvailableLanguages.isEmpty()) 727 { 728 translatedText.put("isMultilingual", true); 729 translatedText.put("values", textForAvailableLanguages); 730 } 731 } 732 else 733 { 734 String label = text.getLabel(); 735 if (StringUtils.isNotBlank(label)) 736 { 737 translatedText.put("isMultilingual", false); 738 translatedText.put("values", label); 739 } 740 } 741 } 742 return translatedText; 743 } 744 } 745 746 /** 747 * Get translations of a text for each available languages 748 * @param text An i18n text 749 * @param useRawValues true to use the raw values 750 * @return All translations of a text 751 */ 752 private Map<String, String> _getTextForAvailableLanguages(I18nizableText text, boolean useRawValues) 753 { 754 Map<String, String> translatedTexts = new HashMap<>(); 755 for (Entry<String, Language> avaibleLanguage : _availableLanguages.entrySet()) 756 { 757 String language = avaibleLanguage.getKey(); 758 String translatedText = _i18nUtils.translate(text, language, useRawValues); 759 if (translatedText != null) 760 { 761 translatedTexts.put(language, translatedText); 762 } 763 } 764 return translatedTexts; 765 } 766}