org.silverpeas.components.classifieds.control.ClassifiedsSessionController.java Source code

Java tutorial

Introduction

Here is the source code for org.silverpeas.components.classifieds.control.ClassifiedsSessionController.java

Source

/*
 * Copyright (C) 2000 - 2018 Silverpeas
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * As a special exception to the terms and conditions of version 3.0 of
 * the GPL, you may redistribute this Program in connection with Free/Libre
 * Open Source Software ("FLOSS") applications as described in Silverpeas's
 * FLOSS exception.  You should have recieved a copy of the text describing
 * the FLOSS exception, and it is also available here:
 * "http://www.silverpeas.org/docs/core/legal/floss_exception.html"
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.silverpeas.components.classifieds.control;

import org.apache.commons.fileupload.FileItem;
import org.silverpeas.components.classifieds.model.ClassifiedDetail;
import org.silverpeas.components.classifieds.model.Subscribe;
import org.silverpeas.components.classifieds.notification.ClassifiedOwnerNotification;
import org.silverpeas.components.classifieds.notification.ClassifiedSimpleNotification;
import org.silverpeas.components.classifieds.service.ClassifiedService;
import org.silverpeas.components.classifieds.service.ClassifiedServiceProvider;
import org.silverpeas.core.ResourceReference;
import org.silverpeas.core.SilverpeasRuntimeException;
import org.silverpeas.core.admin.user.model.UserDetail;
import org.silverpeas.core.comment.service.CommentService;
import org.silverpeas.core.comment.service.CommentServiceProvider;
import org.silverpeas.core.contribution.attachment.AttachmentServiceProvider;
import org.silverpeas.core.contribution.attachment.model.DocumentType;
import org.silverpeas.core.contribution.attachment.model.SimpleAttachment;
import org.silverpeas.core.contribution.attachment.model.SimpleDocument;
import org.silverpeas.core.contribution.attachment.model.SimpleDocumentPK;
import org.silverpeas.core.contribution.content.form.DataRecord;
import org.silverpeas.core.contribution.content.form.RecordSet;
import org.silverpeas.core.contribution.content.form.record.GenericFieldTemplate;
import org.silverpeas.core.contribution.template.publication.PublicationTemplate;
import org.silverpeas.core.contribution.template.publication.PublicationTemplateException;
import org.silverpeas.core.contribution.template.publication.PublicationTemplateManager;
import org.silverpeas.core.index.search.model.QueryDescription;
import org.silverpeas.core.notification.user.ManualUserNotificationSupplier;
import org.silverpeas.core.notification.user.NotificationContext;
import org.silverpeas.core.notification.user.builder.helper.UserNotificationHelper;
import org.silverpeas.core.security.session.SessionInfo;
import org.silverpeas.core.security.session.SessionManagement;
import org.silverpeas.core.security.session.SessionManagementProvider;
import org.silverpeas.core.util.MultiSilverpeasBundle;
import org.silverpeas.core.util.StringUtil;
import org.silverpeas.core.util.file.FileUtil;
import org.silverpeas.core.util.logging.SilverLogger;
import org.silverpeas.core.web.mvc.controller.AbstractComponentSessionController;
import org.silverpeas.core.web.mvc.controller.ComponentContext;
import org.silverpeas.core.web.mvc.controller.MainSessionController;
import org.silverpeas.core.web.mvc.webcomponent.WebMessager;
import org.silverpeas.core.web.util.ListIndex;
import org.silverpeas.core.web.util.viewgenerator.html.pagination.Pagination;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class ClassifiedsSessionController extends AbstractComponentSessionController {

    private static final int DEFAULT_NBITEMS_PERPAGE = 20;
    private static final int SCOPE_ALL = 0;
    private static final int SCOPE_MINE = 1;
    private static final int SCOPE_TOVALIDATE = 2;
    private static final int SCOPE_SEARCH = 3;

    private int currentFirstItemIndex = 0;
    private int nbItemsPerPage = DEFAULT_NBITEMS_PERPAGE;
    private Map<String, String> fields1 = null;
    private Map<String, String> fields2 = null;
    private CommentService commentService = null;
    private MultiSilverpeasBundle resources = null;
    private ClassifiedService classifiedService;

    private SearchContext searchContext = null;
    private List<ClassifiedDetail> sessionClassifieds = null;
    Pagination pagination = null;
    private ListIndex currentIndex = new ListIndex(0);
    private int currentScope = SCOPE_ALL;

    /**
     * Standard Session Controller Constructeur
     * @param mainSessionCtrl The user's profile
     * @param componentContext The component's profile
     */
    public ClassifiedsSessionController(MainSessionController mainSessionCtrl, ComponentContext componentContext) {
        super(mainSessionCtrl, componentContext, "org.silverpeas.classifieds.multilang.classifiedsBundle",
                "org.silverpeas.classifieds.settings.classifiedsIcons",
                "org.silverpeas.classifieds.settings.classifiedsSettings");

        nbItemsPerPage = getResources().getSetting("nbElementsPerPage", DEFAULT_NBITEMS_PERPAGE);

        // affectation du formulaire
        String xmlFormName = getXMLFormName();
        String xmlFormShortName;
        if (StringUtil.isDefined(xmlFormName)) {
            xmlFormShortName = xmlFormName.substring(xmlFormName.indexOf('/') + 1, xmlFormName.indexOf('.'));
            try {
                getPublicationTemplateManager()
                        .addDynamicPublicationTemplate(getComponentId() + ":" + xmlFormShortName, xmlFormName);
            } catch (PublicationTemplateException e) {
                throw new SilverpeasRuntimeException(e);
            }
        }
    }

    public void setPagination(Pagination pagination) {
        this.pagination = pagination;
    }

    /**
     * Gets the resources associated with this session controller.
     * @return all of the resources (messages, settings, icons, ...)
     */
    public synchronized MultiSilverpeasBundle getResources() {
        if (resources == null) {
            resources = new MultiSilverpeasBundle(getMultilang(), getIcon(), getSettings(), getLanguage());
        }
        return resources;
    }

    /**
     * get classified corresponding to classifiedId
     * @param classifiedId : String
     * @return classified : ClassifiedDetail
     */
    public ClassifiedDetail getClassified(String classifiedId) {
        ClassifiedDetail classified = getClassifiedService().getContentById(classifiedId);
        classified.setCreatorName(getUserDetail(classified.getCreatorId()).getDisplayedName());
        classified.setCreatorEmail(getUserDetail(classified.getCreatorId()).geteMail());
        if (StringUtil.isDefined(classified.getValidatorId())) {
            classified.setValidatorName(getUserDetail(classified.getValidatorId()).getDisplayedName());
        }

        return classified;
    }

    /**
     * get the number of classifieds for this instance
     * @return number : String
     */
    public String getNbTotalClassifieds() {
        String nb = getClassifiedService().getNbTotalClassifieds(getComponentId());
        currentIndex.setNbItems(Integer.parseInt(nb));
        return nb;
    }

    /**
     * search all classifieds corresponding to the query
     * @param query : QueryDescription
     */
    public void search(QueryDescription query) {
        setSessionClassifieds(getClassifieds(query));
        currentIndex.setNbItems(getSessionClassifieds().size());
    }

    private List<ClassifiedDetail> getClassifieds(QueryDescription query) {
        query.setSearchingUser(getUserId());
        query.addComponent(getComponentId());
        return getClassifiedService().search(query);
    }

    public List<ClassifiedDetail> getClassifieds(QueryDescription query, int nb) {
        setCurrentScope(SCOPE_ALL);
        List<ClassifiedDetail> classifieds = getClassifieds(query);
        List<ClassifiedDetail> result = new ArrayList<>();
        for (int i = 0; i < nb && i < classifieds.size(); i++) {
            ClassifiedDetail classified = classifieds.get(i);
            enrichClassified(classified);
            result.add(classified);
        }
        return result;
    }

    public List<ClassifiedDetail> getSessionClassifieds() {
        if (sessionClassifieds == null) {
            sessionClassifieds = getAllValidClassifieds();
        }
        return sessionClassifieds;
    }

    private void setSessionClassifieds(List<ClassifiedDetail> classifieds) {
        sessionClassifieds = classifieds;
    }

    public Collection<ClassifiedDetail> getPage() {
        pagination.init(sessionClassifieds.size(), getNbPerPage(), getCurrentFirstItemIndex());
        List<ClassifiedDetail> classifieds = sessionClassifieds.subList(pagination.getFirstItemIndex(),
                pagination.getLastItemIndex());

        // enrich displayed classifieds
        for (ClassifiedDetail classified : classifieds) {
            enrichClassified(classified);
        }

        return classifieds;
    }

    private void enrichClassified(ClassifiedDetail classified) {
        setImagesToClassified(classified);
        getClassifiedService().setClassification(classified, getSearchFields1(), getSearchFields2(),
                getXMLFormName());
    }

    /**
     * get all classifieds for the current user and this instance
     * @return a collection of ClassifiedDetail
     */
    public List<ClassifiedDetail> getClassifiedsByUser() {
        setCurrentScope(SCOPE_MINE);
        setSessionClassifieds(getClassifiedService().getClassifiedsByUser(getComponentId(), getUserId()));
        return sessionClassifieds;
    }

    /**
     * get all classifieds to validate for this instance
     * @return a collection of ClassifiedDetail
     */
    public Collection<ClassifiedDetail> getClassifiedsToValidate() {
        setCurrentScope(SCOPE_TOVALIDATE);
        setSessionClassifieds(getClassifiedService().getClassifiedsToValidate(getComponentId()));
        return sessionClassifieds;
    }

    /**
     * take out draft mode the classified corresponding to classified
     * @param classifiedId : String
     * @param highestRole : ClassifiedsRole
     */
    public synchronized void draftOutClassified(String classifiedId, ClassifiedsRole highestRole) {
        getClassifiedService().draftOutClassified(classifiedId, highestRole.getName(), isValidationEnabled());
        if (!isValidationEnabled()
                && (highestRole == ClassifiedsRole.PUBLISHER || highestRole == ClassifiedsRole.MANAGER)) {
            sendSubscriptionsNotification(classifiedId);
        }
    }

    /**
     * pass the classified corresponding to classifiedId in draft mode
     * @param classifiedId : String
     */
    public synchronized void draftInClassified(String classifiedId) {
        getClassifiedService().draftInClassified(classifiedId);
    }

    /**
     * pass to status validate because the user corresponding to userId validated the classified
     * corresponding to classifiedId
     * @param classifiedId : String
     */
    public synchronized void validateClassified(String classifiedId) {
        getClassifiedService().validateClassified(classifiedId, getUserId());

        // remove classified from validation list
        removeCurrentClassifiedFromSession();

        // alert subscribers
        sendSubscriptionsNotification(classifiedId);
    }

    private void removeCurrentClassifiedFromSession() {
        getSessionClassifieds().remove(currentIndex.getCurrentIndex());
        currentIndex.setNbItems(getSessionClassifieds().size());
        currentIndex.setCurrentIndex(currentIndex.getPreviousIndex());
    }

    /**
     * pass to status refused because the user corresponding to userId refused the classified
     * corresponding to classifiedId for the motive ResusalMotive
     * @param classifiedId : String
     * @param motive : String
     */
    public synchronized void refusedClassified(String classifiedId, String motive) {
        getClassifiedService().refusedClassified(classifiedId, getUserId(), motive);

        // remove classified from validation list
        removeCurrentClassifiedFromSession();
    }

    /**
     * get the name of xmlForm
     * @return name : String
     */
    public String getXMLFormName() {
        return getComponentParameterValue("XMLFormName");
    }

    /**
     * get the name of search field1
     * @return search field1 name : String
     */
    public String getSearchFields1() {
        return getComponentParameterValue("searchFields1");
    }

    /**
     * get the name of search field2
     * @return search field2 name : String
     */
    public String getSearchFields2() {
        return getComponentParameterValue("searchFields2");
    }

    /**
     * create classified
     * @param classified : classifiedDetail
     * @param profile : ClassifiedsRole
     * @return classifiedId : String
     */
    public synchronized String createClassified(ClassifiedDetail classified, Collection<FileItem> listImage,
            ClassifiedsRole profile, boolean publish) {
        UserDetail user = getUserDetail();
        classified.setCreatorId(getUserId());
        classified.setCreationDate(new Date());
        classified.setCreatorName(user.getDisplayedName());
        classified.setCreatorEmail(user.geteMail());
        classified.setInstanceId(getComponentId());
        // status
        if (isDraftEnabled() && !publish) {
            classified.setStatus(ClassifiedDetail.DRAFT);
        } else {
            if (profile == ClassifiedsRole.MANAGER || !isValidationEnabled()) {
                classified.setStatus(ClassifiedDetail.VALID);
            } else {
                classified.setStatus(ClassifiedDetail.TO_VALIDATE);
            }
        }
        String classifiedId = getClassifiedService().createClassified(classified);
        createClassifiedImages(listImage, classifiedId);
        return classifiedId;
    }

    /**
     * delete the classified corresponding to classifiedId
     * @param classifiedId : String
     */
    public void deleteClassified(String classifiedId) {
        //supprime la petite annonce et ses images
        getClassifiedService().deleteClassified(this.getComponentId(), classifiedId);

        //supprime les commentaires
        ResourceReference pk = new ResourceReference(classifiedId, getComponentId());
        getCommentService().deleteAllCommentsOnPublication(ClassifiedDetail.getResourceType(), pk);
    }

    /**
     * update the classified and send notification if isUpdate is true and, if isAdmin is true and
     * classified is in status valid
     * @param classified : ClassifiedDetail
     * @param isUpdate : boolean
     * @param isAdmin : boolean
     */
    public synchronized void updateClassified(ClassifiedDetail classified, boolean isUpdate, boolean isAdmin,
            boolean publish) {
        boolean notify = false;
        if (isUpdate) {
            classified.setUpdateDate(new Date());
            notify = setStatusOnUpdate(classified, isAdmin, publish);
        }
        getClassifiedService().updateClassified(classified, notify);

        // for newly created classifieds by admin : need to force notification
        if (!isUpdate && classified.isValid()) {
            sendSubscriptionsNotification(Integer.toString(classified.getClassifiedId()));
        }
    }

    private boolean setStatusOnUpdate(ClassifiedDetail classified, boolean isAdmin, boolean publish) {
        boolean notify = false;
        if (isDraftEnabled() && classified.isDraft() && !publish) {
            // do nothing
        } else if (!isAdmin && isValidationEnabled() && !classified.isToValidate()) {
            classified.setStatus(ClassifiedDetail.TO_VALIDATE);
            notify = true;
        } else if (isAdmin || !isValidationEnabled()) {
            classified.setStatus(ClassifiedDetail.VALID);
        }
        return notify;
    }

    /**
     * send a notification for subscribers when classified (corresponding to classifiedId) is modified
     * @param classifiedId : String
     */
    private void sendSubscriptionsNotification(String classifiedId) {
        try {
            ClassifiedDetail classified = getClassified(classifiedId);
            PublicationTemplate pubTemplate = getPublicationTemplate();
            if (pubTemplate != null) {
                RecordSet recordSet = pubTemplate.getRecordSet();
                DataRecord data = recordSet.getRecord(classifiedId);
                String field1 = data.getField(getSearchFields1()).getValue();
                String field2 = data.getField(getSearchFields2()).getValue();
                getClassifiedService().sendSubscriptionsNotification(field1, field2, classified);
            }
        } catch (Exception e) {
            SilverLogger.getLogger(this).error("Can't send subscriptions notifications", e);
        }
    }

    /**
     * create a subscription
     * @param subscribe : Subscribe
     */
    public synchronized void createSubscribe(Subscribe subscribe) {
        try {
            subscribe.setUserId(getUserId());
            subscribe.setInstanceId(getComponentId());
            // ajouter les libells des zones du formulaire
            if (fields1 == null) {
                fields1 = createListField(getSearchFields1());
            }
            if (fields2 == null) {
                fields2 = createListField(getSearchFields2());
            }
            subscribe.setFieldName1(fields1.get(subscribe.getField1()));
            subscribe.setFieldName2(fields2.get(subscribe.getField2()));
            getClassifiedService().createSubscribe(subscribe);
        } catch (Exception e) {
            throw new SilverpeasRuntimeException(e);
        }
    }

    /**
     * delete the subscription corresponding to subscribeId
     * @param subscribeId : String
     */
    public void deleteSubscribe(String subscribeId) {
        getClassifiedService().deleteSubscribe(subscribeId);
    }

    /**
     * create a map of fields corresponding to listName
     * @param listName : String
     * @return a Hashtable of <String, String>
     */
    private Map<String, String> createListField(String listName) {
        Map<String, String> fields = Collections.synchronizedMap(new HashMap<>());
        if (StringUtil.isDefined(listName)) {
            // cration de la hashtable (key,value)
            try {
                PublicationTemplate pubTemplate = getPublicationTemplate();
                if (pubTemplate != null) {
                    GenericFieldTemplate field = (GenericFieldTemplate) pubTemplate.getRecordTemplate()
                            .getFieldTemplate(listName);
                    return field.getKeyValuePairs(getLanguage());
                }
            } catch (Exception e) {
                // ERREUR : le champ de recherche renseign n'est pas une liste droulante
                throw new SilverpeasRuntimeException("Field is not a list", e);
            }
        } else {
            // ERREUR : le champs de recherche n'est pas renseign
        }
        return fields;
    }

    /**
     * get all subscriptions for the current user and this instance
     * @return a collection of Subscribe
     */
    public Collection<Subscribe> getSubscribesByUser() {
        Collection<Subscribe> subscribes = getClassifiedService().getSubscribesByUser(getComponentId(),
                getUserId());

        if (fields1 == null) {
            fields1 = createListField(getSearchFields1());
        }
        if (fields2 == null) {
            fields2 = createListField(getSearchFields2());
        }

        for (Subscribe subscribe : subscribes) {
            // ajout des libells
            subscribe.setFieldName1(fields1.get(subscribe.getField1()));
            subscribe.setFieldName2(fields2.get(subscribe.getField2()));
        }

        return subscribes;
    }

    public void setCurrentFirstItemIndex(String index) {
        if (StringUtil.isDefined(index)) {
            this.currentFirstItemIndex = Integer.parseInt(index);
        }
    }

    public int getCurrentFirstItemIndex() {
        return this.currentFirstItemIndex;
    }

    /**
     * return true if draft mode is enabled
     * @return boolean
     */
    public boolean isDraftEnabled() {
        return "yes".equalsIgnoreCase(getComponentParameterValue("draft"));
    }

    public boolean isValidationEnabled() {
        return "yes".equalsIgnoreCase(getComponentParameterValue("validation"));
    }

    private ClassifiedService getClassifiedService() {
        if (classifiedService == null) {
            classifiedService = ClassifiedServiceProvider.getClassifiedService();
        }
        return classifiedService;
    }

    /**
     * Gets a service providing operations on comments.
     * @return a DefaultCommentService instance.
     */
    private CommentService getCommentService() {
        if (commentService == null) {
            commentService = CommentServiceProvider.getCommentService();
        }
        return commentService;
    }

    /**
     * Gets an instance of PublicationTemplateManager.
     * @return an instance of PublicationTemplateManager.
     */
    private PublicationTemplateManager getPublicationTemplateManager() {
        return PublicationTemplateManager.getInstance();
    }

    /**
     * return true if comments feature is enabled
     * @return boolean
     */
    public boolean isCommentsEnabled() {
        return !"no".equalsIgnoreCase(getComponentParameterValue("comments"));
    }

    /**
     * create classified image
     * @param fileImage : FileItem
     * @param classifiedId : String
     */
    public synchronized void createClassifiedImage(FileItem fileImage, String classifiedId) {

        try {
            // create SimpleDocumentPK with componentId
            SimpleDocumentPK sdPK = new SimpleDocumentPK(null, getComponentId());

            // create SimpleDocument Object
            Date creationDate = new Date();
            String fileName = FileUtil.getFilename(fileImage.getName());
            long size = fileImage.getSize();
            String mimeType = FileUtil.getMimeType(fileName);

            SimpleDocument sd = new SimpleDocument(sdPK, classifiedId, 0, false, new SimpleAttachment(fileName,
                    getLanguage(), "", "", size, mimeType, getUserId(), creationDate, null));
            sd.setDocumentType(DocumentType.attachment);

            AttachmentServiceProvider.getAttachmentService().createAttachment(sd, fileImage.getInputStream(), true);
        } catch (Exception e) {
            throw new SilverpeasRuntimeException("Can't save image", e);
        }
    }

    /**
     * create classified images
     * @param listImage : Collection de FileItem
     * @param classifiedId : String
     */
    private synchronized void createClassifiedImages(Collection<FileItem> listImage, String classifiedId) {
        for (FileItem fileImage : listImage) {
            createClassifiedImage(fileImage, classifiedId);
        }
    }

    /**
     * get classified corresponding to classifiedId including images
     * @param classifiedId : String
     * @return classified : ClassifiedDetail
     */
    public ClassifiedDetail getClassifiedWithImages(String classifiedId) {
        ClassifiedDetail classified = getClassified(classifiedId);
        setImagesToClassified(classified);
        processIndex(classified);
        return classified;
    }

    private void setImagesToClassified(ClassifiedDetail classified) {
        if (classified != null) {
            ResourceReference classifiedForeignKey = new ResourceReference(classified.getId(), getComponentId());
            List<SimpleDocument> listSimpleDocument = AttachmentServiceProvider.getAttachmentService()
                    .listDocumentsByForeignKeyAndType(classifiedForeignKey, DocumentType.attachment, null);
            classified.setImages(listSimpleDocument);
        }
    }

    /**
     * update classified image
     * @param fileImage : FileItem
     * @param imageId : String
     * @param classifiedId : String
     */
    public void updateClassifiedImage(FileItem fileImage, String imageId, String classifiedId) {
        SimpleDocumentPK sdPK = new SimpleDocumentPK(imageId, getComponentId());
        SimpleDocument classifiedImage = AttachmentServiceProvider.getAttachmentService().searchDocumentById(sdPK,
                null);

        if (classifiedImage != null) {
            Date updateDate = new Date();
            String fileName = FileUtil.getFilename(fileImage.getName());
            long size = fileImage.getSize();
            String mimeType = FileUtil.getMimeType(fileName);

            classifiedImage.setDocumentType(DocumentType.attachment);
            classifiedImage.setFilename(fileName);
            classifiedImage.setLanguage(null);
            classifiedImage.setTitle("");
            classifiedImage.setDescription("");
            classifiedImage.setSize(size);
            classifiedImage.setContentType(mimeType);
            classifiedImage.setUpdatedBy(getUserId());
            classifiedImage.setUpdated(updateDate);

            try {
                AttachmentServiceProvider.getAttachmentService().updateAttachment(classifiedImage,
                        fileImage.getInputStream(), true, false);
            } catch (Exception e) {
                throw new SilverpeasRuntimeException("Can't save image", e);
            }

        } else {
            createClassifiedImage(fileImage, classifiedId);
        }
    }

    /**
     * delete classified image
     * @param imageId : String
     */
    public void deleteClassifiedImage(String imageId) {
        SimpleDocumentPK sdPK = new SimpleDocumentPK(imageId, getComponentId());
        SimpleDocument classifiedImage = AttachmentServiceProvider.getAttachmentService().searchDocumentById(sdPK,
                null);

        if (classifiedImage != null) {
            //delete the actual picture file in the file server and database
            AttachmentServiceProvider.getAttachmentService().deleteAttachment(classifiedImage);
        } else {
            throw new SilverpeasRuntimeException("Image " + imageId + " does not exist");
        }
    }

    /**
     * return true if Home page displays classifieds organized by category
     * @return boolean
     */
    public boolean isHomePageDisplayCategorized() {
        String parameterHomePage = getComponentParameterValue("homePage");
        if (StringUtil.isDefined(parameterHomePage)) {
            return "0".equalsIgnoreCase(getComponentParameterValue("homePage"));
        }
        return true;
    }

    /**
     * get all valid classifieds
     * @return a collection of ClassifiedDetail
     */
    public List<ClassifiedDetail> getAllValidClassifieds() {
        setCurrentScope(SCOPE_ALL);
        setSessionClassifieds(getClassifiedService().getAllValidClassifieds(getComponentId()));
        if (fields1 == null) {
            fields1 = createListField(getSearchFields1());
        }
        if (fields2 == null) {
            fields2 = createListField(getSearchFields2());
        }
        int nbElementsPerPage = getNbPerPage();
        return getClassifiedService().getAllValidClassifieds(getComponentId(), fields1, fields2, getSearchFields1(),
                getSearchFields2(), getCurrentFirstItemIndex(), nbElementsPerPage);
    }

    public int getNbPerPage() {
        return nbItemsPerPage;
    }

    public void setNbItemsPerPage(String nb) {
        if (StringUtil.isInteger(nb)) {
            nbItemsPerPage = Integer.parseInt(nb);
        }
    }

    /**
     * Gets the template of the publication based on the classified XML form.
     * @return the publication template for classifieds.
     * @throws PublicationTemplateException if an error occurs while getting the publication template.
     */
    public PublicationTemplate getPublicationTemplate() throws PublicationTemplateException {
        PublicationTemplate pubTemplate = null;
        String xmlFormName = getXMLFormName();
        if (StringUtil.isDefined(xmlFormName)) {
            String xmlFormShortName = xmlFormName.substring(xmlFormName.indexOf('/') + 1, xmlFormName.indexOf('.'));
            pubTemplate = getPublicationTemplateManager()
                    .getPublicationTemplate(getComponentId() + ":" + xmlFormShortName, xmlFormName);
        }
        return pubTemplate;
    }

    public void setSearchContext(SearchContext context) {
        setCurrentScope(SCOPE_SEARCH);
        this.searchContext = context;
    }

    public SearchContext getSearchContext() {
        return searchContext;
    }

    public ListIndex getIndex() {
        return currentIndex;
    }

    private void processIndex(ClassifiedDetail classified) {
        currentIndex.setCurrentIndex(getSessionClassifieds().indexOf(classified));
        currentIndex.setNbItems(getSessionClassifieds().size());
    }

    public ClassifiedDetail getPrevious() {
        return getSessionClassifieds().get(currentIndex.getPreviousIndex());
    }

    public ClassifiedDetail getNext() {
        return getSessionClassifieds().get(currentIndex.getNextIndex());
    }

    public int getCurrentScope() {
        return currentScope;
    }

    private void setCurrentScope(int scope) {
        currentScope = scope;
    }

    public void checkScope(ClassifiedDetail classified) {
        if (classified.isToValidate()) {
            getClassifiedsToValidate();
            processIndex(classified);
        }
    }

    @Override
    public ManualUserNotificationSupplier getManualUserNotificationSupplier() {
        return c -> {
            final String instanceId = c.get(NotificationContext.COMPONENT_ID);
            final String sessionKey = c.get("usk");
            final SessionManagement sessionManagement = SessionManagementProvider.getSessionManagement();
            final SessionInfo sessionInfo = sessionManagement.getSessionInfo(sessionKey);
            ClassifiedsSessionController controller = sessionInfo
                    .getAttribute("Silverpeas_classifieds_" + instanceId);
            if (controller == null) {
                throw new SilverpeasRuntimeException("No such classified application: " + instanceId);
            }
            return new ClassifiedSimpleNotification(controller.getCurrentClassified()).build();
        };
    }

    public ClassifiedDetail getCurrentClassified() {
        return getSessionClassifieds().get(currentIndex.getCurrentIndex());
    }

    public void notifyOwner(String message) {
        UserNotificationHelper
                .buildAndSend(new ClassifiedOwnerNotification(getCurrentClassified(), getUserId(), message));
        WebMessager.getInstance().addSuccess(getString("classifieds.notif.sent"));
    }
}