001/* 002 * Copyright 2023 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.cms.search.ui.model; 017 018import java.util.Collection; 019import java.util.Optional; 020 021import org.apache.avalon.framework.configuration.ConfigurationException; 022 023import org.ametys.cms.contenttype.AbstractContentTypeViewParser; 024import org.ametys.cms.contenttype.ContentType; 025import org.ametys.cms.repository.Content; 026import org.ametys.cms.search.model.SystemProperty; 027import org.ametys.plugins.repository.model.CompositeDefinition; 028import org.ametys.plugins.repository.model.RepeaterDefinition; 029import org.ametys.runtime.model.ElementDefinition; 030import org.ametys.runtime.model.Model; 031import org.ametys.runtime.model.ModelHelper.ConfigurationAndPluginName; 032import org.ametys.runtime.model.ModelItem; 033import org.ametys.runtime.model.ModelItemAccessor; 034import org.ametys.runtime.model.ModelViewItem; 035import org.ametys.runtime.model.ModelViewItemGroup; 036import org.ametys.runtime.model.View; 037import org.ametys.runtime.model.ViewItem; 038 039/** 040 * Component that parses the columns of a {@link StaticSearchUIModel} 041 */ 042public class StaticSearchUIModelColumnsParser extends AbstractContentTypeViewParser 043{ 044 private static final String __VIEW_NAME = "StaticSearchUIModel-Columns"; 045 046 /** Content types containing the item available in the search model's columns */ 047 protected Collection<ContentType> _contentTypes; 048 049 /** 050 * Creates a {@link StaticSearchUIModel}'s columns parser 051 * @param contentTypes The content types containing the item available in the search model's columns 052 */ 053 public StaticSearchUIModelColumnsParser(Collection<ContentType> contentTypes) 054 { 055 _contentTypes = contentTypes; 056 } 057 058 @Override 059 protected String _parseViewName(ConfigurationAndPluginName viewConfiguration) throws ConfigurationException 060 { 061 return __VIEW_NAME; 062 } 063 064 @Override 065 public View overrideView(ConfigurationAndPluginName viewConfiguration, View existingView) throws ConfigurationException 066 { 067 throw new UnsupportedOperationException("Unable to override columns of a search model"); 068 } 069 070 @Override 071 protected void _fillViewGeneralInformation(ConfigurationAndPluginName viewConfiguration, View view, View existingView, Collection< ? extends Model> model) throws ConfigurationException 072 { 073 // Do nothing - there is no general information in search model's columns 074 } 075 076 @Override 077 protected Collection<? extends Model> _getModel() 078 { 079 return _contentTypes; 080 } 081 082 @Override 083 protected ModelItem _getModelItem(ConfigurationAndPluginName itemConfiguration, String modelItemName, Collection< ? extends ModelItemAccessor> parents) throws ConfigurationException 084 { 085 ModelItem modelItem = parents.isEmpty() && Content.ATTRIBUTE_TITLE.equals(modelItemName) 086 ? _contentTypesHelper.getTitleAttributeDefinition() 087 : super._getModelItem(itemConfiguration, modelItemName, parents); 088 089 if (modelItem instanceof SystemProperty systemProperty && !systemProperty.isDisplayable()) 090 { 091 throw new ConfigurationException("The property '" + systemProperty.getName() + "' is not displayable."); 092 } 093 094 return modelItem; 095 } 096 097 @Override 098 protected ModelViewItem createModelViewItemForAllItemsReference(ConfigurationAndPluginName itemConfiguration, ModelItem modelItem, View referenceView, boolean override) throws ConfigurationException 099 { 100 if (modelItem instanceof CompositeDefinition compositeDefinition) 101 { 102 ModelViewItemGroup<CompositeDefinition> itemGroup = new ModelViewItemGroup<>(); 103 itemGroup.setDefinition(compositeDefinition); 104 return itemGroup; 105 } 106 else 107 { 108 return super.createModelViewItemForAllItemsReference(itemConfiguration, modelItem, referenceView, override); 109 } 110 } 111 112 @SuppressWarnings("unchecked") 113 @Override 114 protected ModelViewItem createModelViewItem(ConfigurationAndPluginName itemConfiguration, ModelItem modelItem, View referenceView, boolean override) throws ConfigurationException 115 { 116 ModelViewItem<ModelItem> modelViewItem = super.createModelViewItem(itemConfiguration, modelItem, referenceView, override); 117 118 if (modelViewItem instanceof SearchUIColumn searchColumn) 119 { 120 searchColumn.setWidth(itemConfiguration.configuration().getChild("width").getValueAsInteger(-1)); 121 searchColumn.setHidden(itemConfiguration.configuration().getChild("hidden").getValueAsBoolean(false)); 122 123 searchColumn.setEditable(itemConfiguration.configuration().getChild("editable").getValueAsBoolean(true)); 124 searchColumn.setSortable(itemConfiguration.configuration().getChild("sortable").getValueAsBoolean(true)); 125 searchColumn.setAllowSortOnMultipleJoin(itemConfiguration.configuration().getChild("allow-sort-on-multiple-join").getValueAsBoolean(false)); 126 searchColumn.setDefaultSorter(Optional.ofNullable(itemConfiguration.configuration().getChild("default-sorter").getValue(null))); 127 128 searchColumn.setRenderer(Optional.ofNullable(itemConfiguration.configuration().getChild("renderer").getValue(null))); 129 searchColumn.setConverter(Optional.ofNullable(itemConfiguration.configuration().getChild("converter").getValue(null))); 130 } 131 132 return modelViewItem; 133 } 134 135 @Override 136 protected ModelViewItem _createModelViewItemInstance(ModelItem modelItem) 137 { 138 return SearchUIColumnHelper.createModelItemColumn(modelItem); 139 } 140 141 @Override 142 protected ViewItem _createViewItemCopyInstanceForReferencedView(ViewItem viewItem) 143 { 144 return Optional.of(viewItem) 145 .filter(ModelViewItem.class::isInstance) 146 .map(ModelViewItem.class::cast) 147 .map(ModelViewItem::getDefinition) 148 // Keep only items that can be represented in columns 149 .filter(modelViewItem -> modelViewItem instanceof RepeaterDefinition || modelViewItem instanceof ElementDefinition) 150 .map(this::_createModelViewItemInstance) 151 .map(ViewItem.class::cast) 152 .orElseGet(() -> super._createViewItemCopyInstanceForReferencedView(viewItem)); 153 } 154}