From 00ccbb4b4ca86af69c453d441964fe3f85db5bc6 Mon Sep 17 00:00:00 2001 From: evdngsl <158455076+evdngsl@users.noreply.github.com> Date: Tue, 13 May 2025 16:28:33 +0200 Subject: [PATCH 1/2] LUT-29994 : Paginator injection --- .../paris/lutece/portal/web/util/IPager.java | 100 ++++++++++++++++++ .../paris/lutece/portal/web/util/Pager.java | 61 +++++++++++ .../lutece/portal/web/util/PagerProducer.java | 68 ++++++++++++ .../portal/web/util/PaginatorHandler.java | 62 +++++++++++ .../lutece/portal/web/util/SimplePager.java | 98 +++++++++++++++++ 5 files changed, 389 insertions(+) create mode 100644 src/java/fr/paris/lutece/portal/web/util/IPager.java create mode 100644 src/java/fr/paris/lutece/portal/web/util/Pager.java create mode 100644 src/java/fr/paris/lutece/portal/web/util/PagerProducer.java create mode 100644 src/java/fr/paris/lutece/portal/web/util/PaginatorHandler.java create mode 100644 src/java/fr/paris/lutece/portal/web/util/SimplePager.java diff --git a/src/java/fr/paris/lutece/portal/web/util/IPager.java b/src/java/fr/paris/lutece/portal/web/util/IPager.java new file mode 100644 index 0000000000..7bbc1eab64 --- /dev/null +++ b/src/java/fr/paris/lutece/portal/web/util/IPager.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2002-2025, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.portal.web.util; + +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * + * @param + * @param + */ +public interface IPager +{ + /** + * Gets the name + * + * @return The name of the pager + */ + String getName( ); + + /** + * Returns the paged list model based on the List provided through initList method. + * + * @param + * @param request + * @param locale + * @return + */ + Map getPaginatedListModel( HttpServletRequest request, Locale locale ); + + /** + * Returns the paged list model based on the List provided through initIdList method and the delegate function to load the objects with their ids. + * + * @param + * @param request + * @param delegate + * @param locale + * @return + */ + Map getPaginatedListModel( HttpServletRequest request, Function, List> delegate, Locale locale ); + + /** + * Set the list of IDs . This list will be used to load the objects through getPaginatedListModel method with a delegate on the concrete method that + * will load the complete objects. + * + * @param listIds + */ + void setIdList( List listIds ); + + /** + * Set the list of items. In that case, no delegate will be involved during the retrieval of a page. This method should be used when the pager is of type + * IPager. + * + * @param listItems + */ + void setList( List listItems ); + + /** + * Allows to update the base url of the pager in case this url should be dynamic. + * + * @param strBaseUrl + */ + void setBaseUrl( String strBaseUrl ); +} diff --git a/src/java/fr/paris/lutece/portal/web/util/Pager.java b/src/java/fr/paris/lutece/portal/web/util/Pager.java new file mode 100644 index 0000000000..9e467e5ab0 --- /dev/null +++ b/src/java/fr/paris/lutece/portal/web/util/Pager.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002-2025, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.portal.web.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +public @interface Pager +{ + + @Nonbinding + String name() default ""; + + @Nonbinding + String defaultItemsPerPage() default "50"; + + @Nonbinding + String listBookmark() default "item_list"; + + @Nonbinding + String baseUrl() default ""; +} diff --git a/src/java/fr/paris/lutece/portal/web/util/PagerProducer.java b/src/java/fr/paris/lutece/portal/web/util/PagerProducer.java new file mode 100644 index 0000000000..89c71f8039 --- /dev/null +++ b/src/java/fr/paris/lutece/portal/web/util/PagerProducer.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002-2025, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.portal.web.util; + +import org.eclipse.microprofile.config.Config; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.spi.InjectionPoint; +import jakarta.inject.Inject; + +@ApplicationScoped +public class PagerProducer +{ + + @Inject + private PaginatorHandler paginatorHandler; + + @Inject + Config config; + + @Produces + @Pager( name = "", listBookmark = "", defaultItemsPerPage = "", baseUrl = "" ) + public IPager producePager( InjectionPoint ip ) + { + Pager qualifier = ip.getQualifiers( ).stream( ).filter( Pager.class::isInstance ).map( Pager.class::cast ).findFirst( ).orElse( null ); + String strName = qualifier.name( ); + if ( null == strName || "".equals( strName ) ) + { + strName = ip.getMember( ).getDeclaringClass( ).getName( ); + } + + return paginatorHandler.createPaginator( strName, qualifier.listBookmark( ), qualifier.baseUrl( ), + config.getOptionalValue( qualifier.defaultItemsPerPage( ), Integer.class ).orElse( 50 ) ); + } + +} diff --git a/src/java/fr/paris/lutece/portal/web/util/PaginatorHandler.java b/src/java/fr/paris/lutece/portal/web/util/PaginatorHandler.java new file mode 100644 index 0000000000..6c1aee2f7d --- /dev/null +++ b/src/java/fr/paris/lutece/portal/web/util/PaginatorHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002-2025, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.portal.web.util; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import jakarta.enterprise.context.SessionScoped; + +@SessionScoped +public class PaginatorHandler implements Serializable +{ + + private final Map paginators = new HashMap( ); + + private IPager getPaginator( String strName ) + { + return paginators.get( strName ); + } + + public IPager createPaginator( String strName, String strListBookmark, String strBaseUrl, int nDefaultItemsPerPage ) + { + if ( !paginators.containsKey( strName ) ) + { + paginators.put( strName, new SimplePager( strName, strListBookmark, strBaseUrl, nDefaultItemsPerPage ) ); + } + return getPaginator( strName ); + } + +} diff --git a/src/java/fr/paris/lutece/portal/web/util/SimplePager.java b/src/java/fr/paris/lutece/portal/web/util/SimplePager.java new file mode 100644 index 0000000000..be0ff8e0be --- /dev/null +++ b/src/java/fr/paris/lutece/portal/web/util/SimplePager.java @@ -0,0 +1,98 @@ +package fr.paris.lutece.portal.web.util; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; + +import fr.paris.lutece.util.html.AbstractPaginator; +import fr.paris.lutece.util.url.UrlItem; +import jakarta.servlet.http.HttpServletRequest; + +/** + * Simple implementation of the IPager + * + * @param + * @param + */ +public class SimplePager implements IPager, Serializable +{ + private static final String MARK_PAGINATOR = "paginator"; + private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page"; + + private final String _strName; + private String _strListBookmark; + private String _strBaseUrl; + private String _strCurrentPageIndex; + private int _nDefaultItemsPerPage; + private int _nItemsPerPage; + private List _listId; + + public String getName( ) + { + return _strName; + } + + public SimplePager( String strName, String strListBookmark, String strBaseUrl, int nDefaultItemsPerPage ) + { + _strName = strName; + _strListBookmark = strListBookmark; + _strBaseUrl = strBaseUrl; + _nDefaultItemsPerPage = nDefaultItemsPerPage; + } + + @Override + public Map getPaginatedListModel( HttpServletRequest request, Locale locale ) + { + return getPaginatedListModel( request, null, locale ); + } + + @Override + public Map getPaginatedListModel( HttpServletRequest request, Function, List> delegate, Locale locale ) + { + _strCurrentPageIndex = AbstractPaginator.getPageIndex( request, AbstractPaginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex ); + _nItemsPerPage = AbstractPaginator.getItemsPerPage( request, AbstractPaginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage, _nDefaultItemsPerPage ); + + UrlItem url = new UrlItem( _strBaseUrl ); + String strUrl = url.getUrl( ); + + LocalizedPaginator paginator = new LocalizedPaginator( _listId, _nItemsPerPage, strUrl, AbstractPaginator.PARAMETER_PAGE_INDEX, + _strCurrentPageIndex, locale ); + + Map model = new HashMap( ); + model.put( MARK_NB_ITEMS_PER_PAGE, String.valueOf( _nItemsPerPage ) ); + model.put( MARK_PAGINATOR, paginator ); + if ( null != delegate ) + { + model.put( _strListBookmark, delegate.apply( paginator.getPageItems( ) ) ); + } + else + { + model.put( _strListBookmark, paginator.getPageItems( ) ); + } + return model; + } + + @Override + public void setIdList( List listItems ) + { + _listId = listItems; + _strCurrentPageIndex = null; + } + + @Override + public void setList( List listItems ) + { + _listId = listItems; + _strCurrentPageIndex = null; + } + + @Override + public void setBaseUrl( String strBaseUrl ) + { + _strBaseUrl = strBaseUrl; + } + +} From 6d6d5a6d71976e8174abd20ea29aec107f707177 Mon Sep 17 00:00:00 2001 From: evdngsl <158455076+evdngsl@users.noreply.github.com> Date: Tue, 13 May 2025 16:29:21 +0200 Subject: [PATCH 2/2] LUT-29994 : Paginator injection setup in styles JspBeans --- .../portal/web/style/StylesJspBean.java | 34 +++++++------------ .../web/stylesheet/StyleSheetJspBean.java | 33 ++++++++---------- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/java/fr/paris/lutece/portal/web/style/StylesJspBean.java b/src/java/fr/paris/lutece/portal/web/style/StylesJspBean.java index b58f83f371..8ae0f0065a 100644 --- a/src/java/fr/paris/lutece/portal/web/style/StylesJspBean.java +++ b/src/java/fr/paris/lutece/portal/web/style/StylesJspBean.java @@ -39,7 +39,8 @@ import java.util.List; import java.util.Map; -import jakarta.enterprise.context.SessionScoped; +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.servlet.http.HttpServletRequest; @@ -56,19 +57,18 @@ import fr.paris.lutece.portal.service.message.AdminMessageService; import fr.paris.lutece.portal.service.security.SecurityTokenService; import fr.paris.lutece.portal.service.template.AppTemplateService; -import fr.paris.lutece.portal.service.util.AppPropertiesService; import fr.paris.lutece.portal.web.admin.AdminFeaturesPageJspBean; import fr.paris.lutece.portal.web.constants.Messages; import fr.paris.lutece.portal.web.constants.Parameters; -import fr.paris.lutece.portal.web.util.LocalizedPaginator; -import fr.paris.lutece.util.html.AbstractPaginator; +import fr.paris.lutece.portal.web.util.IPager; +import fr.paris.lutece.portal.web.util.Pager; import fr.paris.lutece.util.html.HtmlTemplate; import fr.paris.lutece.util.sort.AttributeComparator; /** * This class provides the user interface to manage Styles features */ -@SessionScoped +@RequestScoped @Named public class StylesJspBean extends AdminFeaturesPageJspBean { @@ -91,8 +91,6 @@ public class StylesJspBean extends AdminFeaturesPageJspBean private static final String MARK_PORTLET_TYPE_LIST = "portlet_type_list"; private static final String MARK_PORTAL_COMPONENT_LIST = "portal_component_list"; private static final String MARK_STYLE = "style"; - private static final String MARK_PAGINATOR = "paginator"; - private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page"; // Properties private static final String PROPERTY_STYLES_PER_PAGE = "paginator.style.itemsPerPage"; @@ -117,8 +115,10 @@ public class StylesJspBean extends AdminFeaturesPageJspBean private static final String MESSAGE_CREATE_STYLE_ID_ALREADY_EXISTS = "portal.style.message.createStyle.idAlreadyExists"; private static final String MESSAGE_CREATE_STYLE_COMPONENT_EXISTS = "portal.style.message.createStyle.componentHasAlreadyAStyle"; private static final String MESSAGE_CONFIRM_DELETE_STYLESHEET = "portal.style.message.stylesheetConfirmDelete"; - private int _nItemsPerPage; - private String _strCurrentPageIndex; + + @Inject + @Pager( listBookmark = MARK_STYLE_LIST, defaultItemsPerPage = PROPERTY_STYLES_PER_PAGE) + private IPager pager; /** * Displays the styles list @@ -142,10 +142,7 @@ public String getStylesManagement( HttpServletRequest request ) Collections.sort( listStyles, new AttributeComparator( strSortedAttributeName, bIsAscSort ) ); } - - int defaultItemsPerPage = AppPropertiesService.getPropertyInt( PROPERTY_STYLES_PER_PAGE, 10 ); - _strCurrentPageIndex = AbstractPaginator.getPageIndex( request, AbstractPaginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex ); - _nItemsPerPage = AbstractPaginator.getItemsPerPage( request, AbstractPaginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage, defaultItemsPerPage ); + pager.setList( listStyles ); String strURL = getHomeUrl( request ); @@ -158,15 +155,10 @@ public String getStylesManagement( HttpServletRequest request ) { strURL += ( "&" + Parameters.SORTED_ASC + "=" + strAscSort ); } + pager.setBaseUrl( strURL ); - LocalizedPaginator