<commit_before>/*
 * (C) Copyright 2007-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     <NAME>
 *     <NAME>
 *     <NAME>
 *     <NAME>
 */

package org.nuxeo.ecm.platform.publisher.web;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.context.FacesContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.core.Events;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.PathRef;
import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
import org.nuxeo.ecm.core.api.event.CoreEventConstants;
import org.nuxeo.ecm.core.api.event.DocumentEventCategories;
import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.event.Event;
import org.nuxeo.ecm.core.event.EventProducer;
import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
import org.nuxeo.ecm.core.schema.FacetNames;
import org.nuxeo.ecm.core.schema.SchemaManager;
import org.nuxeo.ecm.platform.publisher.api.PublicationNode;
import org.nuxeo.ecm.platform.publisher.api.PublicationTree;
import org.nuxeo.ecm.platform.publisher.api.PublicationTreeNotAvailable;
import org.nuxeo.ecm.platform.publisher.api.PublishedDocument;
import org.nuxeo.ecm.platform.publisher.api.PublisherException;
import org.nuxeo.ecm.platform.publisher.api.PublisherService;
import org.nuxeo.ecm.platform.publisher.api.PublishingEvent;
import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager;
import org.nuxeo.ecm.webapp.helpers.EventManager;
import org.nuxeo.ecm.webapp.helpers.EventNames;
import org.nuxeo.runtime.api.Framework;

/**
 * This Seam bean manages the publishing tab.
 * 
 * @author <a href="mailto:<EMAIL>">Th<NAME></a>
 */
@Name("publishActions")
@Scope(ScopeType.CONVERSATION)
public class PublishActionsBean extends AbstractPublishActions implements
        Serializable {

    public static class PublicationTreeInformation {

        private final String name;

        private final String title;

        public PublicationTreeInformation(String treeName, String treeTitle) {
            this.name = treeName;
            this.title = treeTitle;
        }

        public String getName() {
            return name;
        }

        public String getTitle() {
            return title;
        }
    }

    private static final long serialVersionUID = 1L;

    private static final Log log = LogFactory.getLog(PublishActionsBean.class);

    @In(create = true)
    protected transient DocumentsListsManager documentsListsManager;

    @In(create = true, required = false)
    protected transient FacesMessages facesMessages;

    protected transient PublisherService publisherService;

    protected String currentPublicationTreeNameForPublishing;

    protected PublicationTree currentPublicationTree;

    protected String publishingComment;

    protected static Set<String> sectionTypes;

    protected Map<String, String> publicationParameters = new HashMap<String, String>();

    protected String treeSID;

    @Create
    public void create() {
        try {
            publisherService = Framework.getService(PublisherService.class);
        } catch (Exception e) {
            throw new IllegalStateException("Publisher service not deployed.",
                    e);
        }
    }

    @Destroy
    public void destroy() {
        if (currentPublicationTree != null) {
            currentPublicationTree.release();
            currentPublicationTree = null;
        }
        if (treeSID != null) {
            publisherService.releaseAllTrees(treeSID);
        }
    }

    protected Map<String, String> filterEmptyTrees(Map<String, String> trees)
            throws PublicationTreeNotAvailable, ClientException {

        Map<String, String> filteredTrees = new HashMap<String, String>();

        List<String> prefilteredTrees = filterEmptyTrees(trees.keySet());

        for (String ptree : prefilteredTrees) {
            filteredTrees.put(ptree, trees.get(ptree));
        }

        return filteredTrees;
    }

    protected List<String> filterEmptyTrees(Collection<String> trees)
            throws PublicationTreeNotAvailable, ClientException {
        List<String> filteredTrees = new ArrayList<String>();

        for (String tree : trees) {
            try {
                PublicationTree pTree = publisherService.getPublicationTree(
                        tree, documentManager, null,
                        navigationContext.getCurrentDocument());
                if (pTree != null) {
                    if (pTree.getTreeType().equals(
                            "RootSectionsPublicationTree")) {
                        if (pTree.getChildrenNodes().size() > 0) {
                            filteredTrees.add(tree);
                        }
                    } else {
                        filteredTrees.add(tree);
                    }
                }
            } catch (PublicationTreeNotAvailable e) {
                log.warn("Publication tree " + tree
                        + " is not available : check config");
                log.debug("Publication tree " + tree
                        + " is not available : root cause is ", e);
            }
        }
        return filteredTrees;
    }

    @Factory(value = "availablePublicationTrees", scope = ScopeType.EVENT)
    public List<PublicationTreeInformation> getAvailablePublicationTrees()
            throws ClientException {
        Map<String, String> trees = publisherService.getAvailablePublicationTrees();
        // remove empty trees
        trees = filterEmptyTrees(trees);
        List<PublicationTreeInformation> treesInformation = new ArrayList<PublicationTreeInformation>();
        for (Map.Entry<String, String> entry : trees.entrySet()) {
            treesInformation.add(new PublicationTreeInformation(entry.getKey(),
                    entry.getValue()));
        }
        return treesInformation;
    }

    public String doPublish(PublicationNode publicationNode)
            throws ClientException {
        PublicationTree tree = getCurrentPublicationTreeForPublishing();
        return doPublish(tree, publicationNode);
    }

    public String doPublish(PublicationTree tree,
            PublicationNode publicationNode) throws ClientException {
        if (tree == null) {
            return null;
        }

        DocumentModel currentDocument = navigationContext.getCurrentDocument();

        PublishedDocument publishedDocument;
        try {
            publishedDocument = tree.publish(currentDocument, publicationNode,
                    publicationParameters);
        } catch (PublisherException e) {
            log.error(e, e);
            facesMessages.add(StatusMessage.Severity.ERROR,
                    resourcesAccessor.getMessages().get(e.getMessage()));
            return null;
        }

        FacesContext context = FacesContext.getCurrentInstance();
        if (publishedDocument.isPending()) {
            String comment = ComponentUtils.translate(context,
                    "publishing.waiting", publicationNode.getPath(),
                    tree.getConfigName());
            // Log event on live version
            notifyEvent(PublishingEvent.documentWaitingPublication.name(),
                    null, comment, null, currentDocument);
            Events.instance().raiseEvent(
                    EventNames.DOCUMENT_SUBMITED_FOR_PUBLICATION);
            facesMessages.add(
                    StatusMessage.Severity.INFO,
                    resourcesAccessor.getMessages().get(
                            "document_submitted_for_publication"),
                    resourcesAccessor.getMessages().get(
                            currentDocument.getType()));
        } else {
            String comment = ComponentUtils.translate(context,
                    "publishing.done", publicationNode.getPath(),
                    tree.getConfigName());
            // Log event on live version
            notifyEvent(PublishingEvent.documentPublished.name(), null,
                    comment, null, currentDocument);
            Events.instance().raiseEvent(EventNames.DOCUMENT_PUBLISHED);
            // publish may checkin the document -> change
            Events.instance().raiseEvent(EventNames.DOCUMENT_CHANGED);
            facesMessages.add(
                    StatusMessage.Severity.INFO,
                    resourcesAccessor.getMessages().get("document_published"),
                    resourcesAccessor.getMessages().get(
                            currentDocument.getType()));
        }
        return null;
    }

    public void setCurrentPublicationTreeNameForPublishing(
            String currentPublicationTreeNameForPublishing)
            throws ClientException {
        this.currentPublicationTreeNameForPublishing = currentPublicationTreeNameForPublishing;<commit_msg>NXP-9819: set currentPublicationTree to null to force its computation when displaying publication tree after publishing<commit_after>/*
 * (C) Copyright 2007-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     <NAME>
 *     <NAME>
 *     <NAME>ins
 *     <NAME>
 */

package org.nuxeo.ecm.platform.publisher.web;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.context.FacesContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.core.Events;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.PathRef;
import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
import org.nuxeo.ecm.core.api.event.CoreEventConstants;
import org.nuxeo.ecm.core.api.event.DocumentEventCategories;
import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.event.Event;
import org.nuxeo.ecm.core.event.EventProducer;
import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
import org.nuxeo.ecm.core.schema.FacetNames;
import org.nuxeo.ecm.core.schema.SchemaManager;
import org.nuxeo.ecm.platform.publisher.api.PublicationNode;
import org.nuxeo.ecm.platform.publisher.api.PublicationTree;
import org.nuxeo.ecm.platform.publisher.api.PublicationTreeNotAvailable;
import org.nuxeo.ecm.platform.publisher.api.PublishedDocument;
import org.nuxeo.ecm.platform.publisher.api.PublisherException;
import org.nuxeo.ecm.platform.publisher.api.PublisherService;
import org.nuxeo.ecm.platform.publisher.api.PublishingEvent;
import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager;
import org.nuxeo.ecm.webapp.helpers.EventManager;
import org.nuxeo.ecm.webapp.helpers.EventNames;
import org.nuxeo.runtime.api.Framework;

/**
 * This Seam bean manages the publishing tab.
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
@Name("publishActions")
@Scope(ScopeType.CONVERSATION)
public class PublishActionsBean extends AbstractPublishActions implements
        Serializable {

    public static class PublicationTreeInformation {

        private final String name;

        private final String title;

        public PublicationTreeInformation(String treeName, String treeTitle) {
            this.name = treeName;
            this.title = treeTitle;
        }

        public String getName() {
            return name;
        }

        public String getTitle() {
            return title;
        }
    }

    private static final long serialVersionUID = 1L;

    private static final Log log = LogFactory.getLog(PublishActionsBean.class);

    @In(create = true)
    protected transient DocumentsListsManager documentsListsManager;

    @In(create = true, required = false)
    protected transient FacesMessages facesMessages;

    protected transient PublisherService publisherService;

    protected String currentPublicationTreeNameForPublishing;

    protected PublicationTree currentPublicationTree;

    protected String publishingComment;

    protected static Set<String> sectionTypes;

    protected Map<String, String> publicationParameters = new HashMap<String, String>();

    protected String treeSID;

    @Create
    public void create() {
        try {
            publisherService = Framework.getService(PublisherService.class);
        } catch (Exception e) {
            throw new IllegalStateException("Publisher service not deployed.",
                    e);
        }
    }

    @Destroy
    public void destroy() {
        if (currentPublicationTree != null) {
            currentPublicationTree.release();
            currentPublicationTree = null;
        }
        if (treeSID != null) {
            publisherService.releaseAllTrees(treeSID);
        }
    }

    protected Map<String, String> filterEmptyTrees(Map<String, String> trees)
            throws PublicationTreeNotAvailable, ClientException {

        Map<String, String> filteredTrees = new HashMap<String, String>();

        List<String> prefilteredTrees = filterEmptyTrees(trees.keySet());

        for (String ptree : prefilteredTrees) {
            filteredTrees.put(ptree, trees.get(ptree));
        }

        return filteredTrees;
    }

    protected List<String> filterEmptyTrees(Collection<String> trees)
            throws PublicationTreeNotAvailable, ClientException {
        List<String> filteredTrees = new ArrayList<String>();

        for (String tree : trees) {
            try {
                PublicationTree pTree = publisherService.getPublicationTree(
                        tree, documentManager, null,
                        navigationContext.getCurrentDocument());
                if (pTree != null) {
                    if (pTree.getTreeType().equals(
                            "RootSectionsPublicationTree")) {
                        if (pTree.getChildrenNodes().size() > 0) {
                            filteredTrees.add(tree);
                        }
                    } else {
                        filteredTrees.add(tree);
                    }
                }
            } catch (PublicationTreeNotAvailable e) {
                log.warn("Publication tree " + tree
                        + " is not available : check config");
                log.debug("Publication tree " + tree
                        + " is not available : root cause is ", e);
            }
        }
        return filteredTrees;
    }

    @Factory(value = "availablePublicationTrees", scope = ScopeType.EVENT)
    public List<PublicationTreeInformation> getAvailablePublicationTrees()
            throws ClientException {
        Map<String, String> trees = publisherService.getAvailablePublicationTrees();
        // remove empty trees
        trees = filterEmptyTrees(trees);
        List<PublicationTreeInformation> treesInformation = new ArrayList<PublicationTreeInformation>();
        for (Map.Entry<String, String> entry : trees.entrySet()) {
            treesInformation.add(new PublicationTreeInformation(entry.getKey(),
                    entry.getValue()));
        }
        return treesInformation;
    }

    public String doPublish(PublicationNode publicationNode)
            throws ClientException {
        PublicationTree tree = getCurrentPublicationTreeForPublishing();
        return doPublish(tree, publicationNode);
    }

    public String doPublish(PublicationTree tree,
            PublicationNode publicationNode) throws ClientException {
        if (tree == null) {
            return null;
        }

        DocumentModel currentDocument = navigationContext.getCurrentDocument();

        PublishedDocument publishedDocument;
        try {
            publishedDocument = tree.publish(currentDocument, publicationNode,
                    publicationParameters);
        } catch (PublisherException e) {
            log.error(e, e);
            facesMessages.add(StatusMessage.Severity.ERROR,
                    resourcesAccessor.getMessages().get(e.getMessage()));
            return null;
        }

        FacesContext context = FacesContext.getCurrentInstance();
        if (publishedDocument.isPending()) {
            String comment = ComponentUtils.translate(context,
                    "publishing.waiting", publicationNode.getPath(),
                    tree.getConfigName());
            // Log event on live version
            notifyEvent(PublishingEvent.documentWaitingPublication.name(),
                    null, comment, null, currentDocument);
            Events.instance().raiseEvent(
                    EventNames.DOCUMENT_SUBMITED_FOR_PUBLICATION);
            facesMessages.add(
                    StatusMessage.Severity.INFO,
                    resourcesAccessor.getMessages().get(
                            "document_submitted_for_publication"),
                    resourcesAccessor.getMessages().get(
                            currentDocument.getType()));
        } else {
            String comment = ComponentUtils.translate(context,
                    "publishing.done", publicationNode.getPath(),
                    tree.getConfigName());
            // Log event on live version
            notifyEvent(PublishingEvent.documentPublished.name(), null,
                    comment, null, currentDocument);
            Events.instance().raiseEvent(EventNames.DOCUMENT_PUBLISHED);
            // publish may checkin the document -> change
            Events.instance().raiseEvent(EventNames.DOCUMENT_CHANGED);
            facesMessages.add(
                    StatusMessage.Severity.INFO,
                    resourcesAccessor.getMessages().get("document_published"),
                    resourcesAccessor.getMessages().get(
                            currentDocument.getType()));
        }
        currentPublicationTree = null;
        return null;
    }

    public void setCurrentPublicationTreeNameForPublishing(
            String currentPublicationTreeNameForPublishing)
            throws ClientException {
        this.currentPublicationTreeNameForPublishing = currentPublicationTreeNameForPublishing;
{'fraction_non_alphanumeric': 0.08912502393260578, 'fraction_numerical': 0.0013402259237985832, 'mean_word_length': 2.6304083405734144, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3027406', 'n_tokens_mistral': 5695, 'n_tokens_neox': 5355, 'n_words': 1129}