001/*
002 *  Copyright 2012 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.web.frontoffice;
017
018import java.util.List;
019import java.util.Optional;
020
021import org.apache.avalon.framework.configuration.Configuration;
022import org.apache.avalon.framework.configuration.ConfigurationException;
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
028import org.ametys.runtime.model.ModelItem;
029import org.ametys.runtime.model.ModelItemGroup;
030import org.ametys.runtime.model.ModelViewItem;
031import org.ametys.runtime.model.ViewHelper;
032import org.ametys.runtime.model.ViewItem;
033import org.ametys.runtime.model.ViewItemGroup;
034import org.ametys.runtime.model.exception.UndefinedItemPathException;
035import org.ametys.web.repository.page.Page;
036import org.ametys.web.repository.page.ZoneItem;
037import org.ametys.web.service.StaticService;
038
039/**
040 * Service which can be cacheable or not, depending on a parameter.
041 */
042public class SearchPagesService extends StaticService
043{
044    /** The additional parameter for FO search extension point */
045    protected AdditionalParameterFOSearchExtensionPoint _additionalParameterFOSearch;
046    
047    @Override
048    public void service(ServiceManager smanager) throws ServiceException
049    {
050        super.service(smanager);
051        _additionalParameterFOSearch = (AdditionalParameterFOSearchExtensionPoint) smanager.lookup(AdditionalParameterFOSearchExtensionPoint.ROLE);
052    }
053    
054    @Override
055    public boolean isCacheable(Page currentPage, ZoneItem zoneItem)
056    {
057        ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters();
058        
059        if (serviceParameters.getValueOrDefault("search-mode", StringUtils.EMPTY).equals("criteria-only"))
060        {
061            String resultsPageId = serviceParameters.getValueOrDefault("page-with-search", StringUtils.EMPTY);
062            
063            return !resultsPageId.equals(currentPage.getId());
064        }
065        
066        return false;
067    }
068    
069    @Override
070    protected void configureParameters(Configuration parametersConfiguration) throws ConfigurationException
071    {
072        super.configureParameters(parametersConfiguration);
073        
074        for (String additionalParamExtentionId : _additionalParameterFOSearch.getExtensionsIds())
075        {
076            Configuration paramsConfiguration = _additionalParameterFOSearch.getExtension(additionalParamExtentionId);
077            String pluginName = _additionalParameterFOSearch.getPluginName(additionalParamExtentionId);
078            
079            for (Configuration paramConfiguration : paramsConfiguration.getChildren())
080            {
081                // Parse the item to insert
082                String paramName = paramConfiguration.getName();
083                ModelViewItem itemToInsert = paramName.equals("repeater") ? _viewAndParametersParser.parseRepeater(paramConfiguration, null, pluginName, "plugin." + pluginName, _view, _modelItems, this, _serviceParameterDefinitionParser, _repeaterDefinitionParser) : _viewAndParametersParser.parseParameter(paramConfiguration, null, pluginName, "plugin." + pluginName, _view, _modelItems, this, _serviceParameterDefinitionParser, _repeaterDefinitionParser);
084
085                if (itemToInsert != null)
086                {
087                    String insertAfter = paramConfiguration.getAttribute("insertAfter", null);
088                    
089                    // Insert the item after the item with the given name
090                    _insertItemAfter(itemToInsert, Optional.ofNullable(insertAfter));
091                }
092            }
093        }
094    }
095    
096    private void _insertItemAfter(ModelViewItem viewItemToInsert, Optional<String> insertAfter) throws ConfigurationException
097    {
098        if (insertAfter.isPresent())
099        {
100            try
101            {
102                ModelViewItem insertAfterViewItem = _view.getModelViewItem(insertAfter.get());
103                if (insertAfterViewItem != null)
104                {
105                    ViewHelper.insertViewItemAfter(insertAfterViewItem.getParent(), viewItemToInsert, insertAfter.get());
106                    
107                    // Insert the corresponding model item in the right model item container
108                    ModelItem modelItemToInsert = viewItemToInsert.getDefinition();
109                    ModelItemGroup parent = insertAfterViewItem.getDefinition().getParent();
110                    if (parent != null)
111                    {
112                        parent.addChild(modelItemToInsert);
113                    }
114                    else
115                    {
116                        _modelItems.put(modelItemToInsert.getName(), modelItemToInsert);
117                    }
118                }
119                else
120                {
121                    getLogger().warn("For service {}, could not find the item with name '{}' to insert after. The attribute {} will be added at the end of the view.", this.getId(), insertAfter.get(), viewItemToInsert.getName());
122                    _insertItemAtTheEnd(viewItemToInsert);
123                }
124            }
125            catch (UndefinedItemPathException | IllegalArgumentException ex)
126            {
127                throw new ConfigurationException("Could not add the attribute " + viewItemToInsert.getName() + " after " + insertAfter.get(), ex);
128            }
129        }
130        else
131        {
132            _insertItemAtTheEnd(viewItemToInsert);
133        }
134    }
135
136    private void _insertItemAtTheEnd(ModelViewItem viewItemToInsert)
137    {
138        // Insert the item at the end of the last group
139        List<ViewItem> firstLevelGroups = _view.getViewItems();
140        
141        ViewItem lastElement = firstLevelGroups.get(firstLevelGroups.size() - 1);
142        if (lastElement instanceof ViewItemGroup lastGroup)
143        {
144            // There are only groups in the view, so we can cast without checking
145            lastGroup.addViewItem(viewItemToInsert);
146        }
147        else
148        {
149            // There are no groups in the view, just add the item at the end of the view
150            _view.addViewItem(viewItemToInsert);
151        }
152        
153        // Insert the corresponding model item in the service
154        ModelItem itemToInsertDefinition = viewItemToInsert.getDefinition();
155        _modelItems.put(itemToInsertDefinition.getName(), itemToInsertDefinition);
156    }
157}