001/*
002 *  Copyright 2020 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.runtime.model;
017
018import java.util.List;
019
020import org.apache.commons.lang3.StringUtils;
021
022/**
023 * Interface for objects that can access to some view items
024 */
025public interface ViewItemAccessor
026{
027    /**
028     * Retrieves all the view items of this accessor
029     * @return the view items
030     */
031    public List<ViewItem> getViewItems();
032    
033    /**
034     * Add a view item in the accessor
035     * @param item the item to add
036     */
037    public void addViewItem(ViewItem item);
038    
039    /**
040     * Insert a view item in the accessor at the given index
041     * @param item the item to insert
042     * @param index index at which the item has to be inserted
043     */
044    public void insertViewItem(ViewItem item, int index);
045    
046    /**
047     * Removes the given items of this accessor
048     * @param item the item to remove
049     * @return <code>true</code> if this accessor contained the given item, <code>false</code> otherwise
050     */
051    public boolean removeViewItem(ViewItem item);
052    
053    /**
054     * Removes all items of this accessor
055     */
056    public void clear();
057    
058    /**
059     * Add view items in the accessor
060     * @param items the items to add
061     */
062    public default void addViewItems(List<ViewItem> items)
063    {
064        for (ViewItem item : items)
065        {
066            addViewItem(item);
067        }
068    }
069    
070    /**
071     * Checks if the current {@link ViewItemAccessor} contains the given model view item
072     * Consider that the accessor contains the given item if it contains an item representing the same definition
073     * @param item the item
074     * @return <code>true</code> if the accessor contains the given item, <code>false</code> otherwise 
075     */
076    public default boolean hasModelViewItem(ModelViewItem item)
077    {
078        return hasModelViewItem(item, StringUtils.EMPTY, item.getDefinition().getPath());
079    }
080    
081    /**
082     * Checks if the current {@link ViewItemAccessor} contains the given model view item
083     * Consider that the accessor contains the given item if it contains an item representing the same definition AND with the same children if it is a group AND at the same position as the given path
084     * @param item the item
085     * @param currentAccessorPath The path of the current item accessor
086     * @param itemPath the path of the item in the accessor
087     * @return <code>true</code> if the accessor contains the given item, <code>false</code> otherwise 
088     */
089    public default boolean hasModelViewItem(ModelViewItem item, String currentAccessorPath, String itemPath)
090    {
091        for (ViewItem currentItem : getViewItems())
092        {
093            String currentItemPath = currentAccessorPath;
094            if (currentItem instanceof ModelViewItem)
095            {
096                currentItemPath += StringUtils.isNotEmpty(currentAccessorPath) ? ModelItem.ITEM_PATH_SEPARATOR + currentItem.getName() : currentItem.getName();
097                if (currentItemPath.equals(itemPath) && currentItem.equals(item))
098                {
099                    return true;
100                }
101            }
102            
103            if (currentItem instanceof ViewItemAccessor && ((ViewItemAccessor) currentItem).hasModelViewItem(item, currentItemPath, itemPath))
104            {
105                return true;
106            }
107        }
108        
109        // No item found
110        return false;
111    }
112    
113    /**
114     * Checks if there is a model view item with the given name
115     * @param itemName the name of the item
116     * @return <code>true</code> if the accessor can access to an item with the given name, <code>false</code> otherwise 
117     */
118    public default boolean hasModelViewItem(String itemName)
119    {
120        return getModelViewItem(itemName) != null;
121    }
122    
123    /**
124     * Retrieves the model view item with the given name
125     * If there are more than one corresponding items, the first one is retrieved
126     * @param itemName the name of the item
127     * @return the model view item, or <code>null</code> if none was found
128     */
129    public default ModelViewItem getModelViewItem(String itemName)
130    {
131        if (StringUtils.isEmpty(itemName))
132        {
133            return null;
134        }
135        else
136        {
137            for (ViewItem item : getViewItems())
138            {
139                // The item is a reference to the model
140                if (item instanceof ModelViewItem modelViewItem)
141                {
142                    if (itemName.equals(item.getName()))
143                    {
144                        return modelViewItem;
145                    }
146                }
147                // The item is not a reference to the model and is a group => check its children
148                else if (item instanceof ViewItemAccessor viewItemAccessor)
149                {
150                    ModelViewItem modelViewItem = viewItemAccessor.getModelViewItem(itemName);
151                    if (modelViewItem != null)
152                    {
153                        return modelViewItem;
154                    }
155                }
156            }
157        
158            // No item found
159            return null;
160        }
161    }
162    
163    /**
164     * Retrieves the view item with the given name
165     * If there are more than one corresponding items, the first one is retrieved
166     * @param itemName the name of the item
167     * @return the view item, or <code>null</code> if none was found
168     */
169    public default ViewItem getViewItem(String itemName)
170    {
171        return getViewItems().stream()
172                             .filter(viewItem -> itemName.equals(viewItem.getName()))
173                             .findFirst()
174                             .orElse(null);
175    }
176}