org.nuxeo.correspondence.web.relations.CorrespondenceRelationActionsBean.java Source code

Java tutorial

Introduction

Here is the source code for org.nuxeo.correspondence.web.relations.CorrespondenceRelationActionsBean.java

Source

/*
 * (C) Copyright 2006-2009 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:
 *     Anahide Tchertchian
 *
 * $Id$
 */

package org.nuxeo.correspondence.web.relations;

import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.event.ActionEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.nuxeo.cm.web.invalidations.CaseManagementContextBound;
import org.nuxeo.cm.web.invalidations.CaseManagementContextBoundInstance;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.event.CoreEventConstants;
import org.nuxeo.ecm.core.event.EventProducer;
import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
import org.nuxeo.ecm.platform.query.api.PageProvider;
import org.nuxeo.ecm.platform.query.api.PageProviderService;
import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider;
import org.nuxeo.ecm.platform.relations.api.Literal;
import org.nuxeo.ecm.platform.relations.api.Node;
import org.nuxeo.ecm.platform.relations.api.QNameResource;
import org.nuxeo.ecm.platform.relations.api.RelationManager;
import org.nuxeo.ecm.platform.relations.api.Resource;
import org.nuxeo.ecm.platform.relations.api.ResourceAdapter;
import org.nuxeo.ecm.platform.relations.api.Statement;
import org.nuxeo.ecm.platform.relations.api.Subject;
import org.nuxeo.ecm.platform.relations.api.event.RelationEvents;
import org.nuxeo.ecm.platform.relations.api.impl.LiteralImpl;
import org.nuxeo.ecm.platform.relations.api.impl.QNameResourceImpl;
import org.nuxeo.ecm.platform.relations.api.impl.RelationDate;
import org.nuxeo.ecm.platform.relations.api.impl.ResourceImpl;
import org.nuxeo.ecm.platform.relations.api.impl.StatementImpl;
import org.nuxeo.ecm.platform.relations.api.util.RelationConstants;
import org.nuxeo.ecm.platform.relations.web.NodeInfo;
import org.nuxeo.ecm.platform.relations.web.NodeInfoImpl;
import org.nuxeo.ecm.platform.relations.web.StatementInfo;
import org.nuxeo.ecm.platform.relations.web.StatementInfoComparator;
import org.nuxeo.ecm.platform.relations.web.StatementInfoImpl;
import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
import org.nuxeo.runtime.api.Framework;

/**
 * Retrieves relations for current email
 *
 * @author Anahide Tchertchian
 */
@Name("correspRelationActions")
@Scope(ScopeType.CONVERSATION)
@CaseManagementContextBound
public class CorrespondenceRelationActionsBean extends CaseManagementContextBoundInstance {

    private static final long serialVersionUID = 1L;

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

    public static final String CURRENT_EMAIL_RELATION_SEARCH_QUERYMODEL = "CURRENT_EMAIL_RELATION_SEARCH";

    @In(create = true)
    protected RelationManager relationManager;

    @In(create = true)
    protected transient ResourcesAccessor resourcesAccessor;

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

    @In(required = false)
    protected transient Principal currentUser;

    // statements lists
    protected List<Statement> incomingStatements;

    protected List<StatementInfo> incomingStatementsInfo;

    protected List<Statement> outgoingStatements;

    protected List<StatementInfo> outgoingStatementsInfo;

    // fields for relation creation

    protected Boolean showCreateForm = false;

    protected String predicateUri;

    protected String comment;

    protected String searchKeywords;

    protected List<String> targetCreationDocuments;

    public DocumentModel getDocumentModel(Node node) throws ClientException {
        if (node.isQNameResource()) {
            QNameResource resource = (QNameResource) node;
            Map<String, Object> context = Collections
                    .<String, Object>singletonMap(ResourceAdapter.CORE_SESSION_CONTEXT_KEY, documentManager);
            Object o = relationManager.getResourceRepresentation(resource.getNamespace(), resource, context);
            if (o instanceof DocumentModel) {
                return (DocumentModel) o;
            }
        }
        return null;
    }

    public QNameResource getDocumentResource(DocumentModel document) throws ClientException {
        QNameResource documentResource = null;
        if (document != null) {
            documentResource = (QNameResource) relationManager.getResource(RelationConstants.DOCUMENT_NAMESPACE,
                    document, null);
        }
        return documentResource;
    }

    protected List<StatementInfo> getStatementsInfo(List<Statement> statements) throws ClientException {
        if (statements == null) {
            return null;
        }
        List<StatementInfo> infoList = new ArrayList<StatementInfo>();
        for (Statement statement : statements) {
            Subject subject = statement.getSubject();
            // TODO: filter on doc visibility (?)
            NodeInfo subjectInfo = new NodeInfoImpl(subject, getDocumentModel(subject), true);
            Resource predicate = statement.getPredicate();
            Node object = statement.getObject();
            NodeInfo objectInfo = new NodeInfoImpl(object, getDocumentModel(object), true);
            StatementInfo info = new StatementInfoImpl(statement, subjectInfo, new NodeInfoImpl(predicate),
                    objectInfo);
            infoList.add(info);
        }
        return infoList;
    }

    public List<StatementInfo> getIncomingStatementsInfo() throws ClientException {
        if (incomingStatementsInfo != null) {
            return incomingStatementsInfo;
        }
        DocumentModel currentDoc = getCurrentCaseItem();
        Resource docResource = getDocumentResource(currentDoc);
        if (docResource == null) {
            incomingStatements = Collections.emptyList();
            incomingStatementsInfo = Collections.emptyList();
        } else {
            Statement pattern = new StatementImpl(null, null, docResource);
            incomingStatements = relationManager.getStatements(RelationConstants.GRAPH_NAME, pattern);
            incomingStatementsInfo = getStatementsInfo(incomingStatements);
            // sort by modification date, reverse
            Comparator<StatementInfo> comp = Collections.reverseOrder(new StatementInfoComparator());
            Collections.sort(incomingStatementsInfo, comp);
        }
        return incomingStatementsInfo;
    }

    public List<StatementInfo> getOutgoingStatementsInfo() throws ClientException {
        if (outgoingStatementsInfo != null) {
            return outgoingStatementsInfo;
        }
        DocumentModel currentDoc = getCurrentCaseItem();
        Resource docResource = getDocumentResource(currentDoc);
        if (docResource == null) {
            outgoingStatements = Collections.emptyList();
            outgoingStatementsInfo = Collections.emptyList();
        } else {
            Statement pattern = new StatementImpl(docResource, null, null);
            outgoingStatements = relationManager.getStatements(RelationConstants.GRAPH_NAME, pattern);
            outgoingStatementsInfo = getStatementsInfo(outgoingStatements);
            // sort by modification date, reverse
            Comparator<StatementInfo> comp = Collections.reverseOrder(new StatementInfoComparator());
            Collections.sort(outgoingStatementsInfo, comp);
        }
        return outgoingStatementsInfo;
    }

    public void resetStatements() {
        incomingStatements = null;
        incomingStatementsInfo = null;
        outgoingStatements = null;
        outgoingStatementsInfo = null;
    }

    // getters & setters for creation items

    public Boolean getShowCreateForm() {
        return showCreateForm;
    }

    public void toggleCreateForm(ActionEvent event) {
        showCreateForm = !showCreateForm;
    }

    public String getPredicateUri() {
        return predicateUri;
    }

    public void setPredicateUri(String predicateUri) {
        this.predicateUri = predicateUri;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getSearchKeywords() {
        return searchKeywords;
    }

    public void setSearchKeywords(String searchKeywords) {
        this.searchKeywords = searchKeywords;
    }

    public List<String> getTargetCreationDocuments() {
        if (targetCreationDocuments == null) {
            targetCreationDocuments = new ArrayList<String>();
        }
        return targetCreationDocuments;
    }

    public void setTargetCreationDocuments(List<String> targetCreationDocuments) {
        this.targetCreationDocuments = targetCreationDocuments;
    }

    protected void resetCreateFormValues() {
        showCreateForm = false;
        predicateUri = null;
        comment = null;
        searchKeywords = null;
        targetCreationDocuments = null;
    }

    protected void notifyEvent(String eventId, DocumentModel source, Map<String, Serializable> options,
            String comment) {
        EventProducer evtProducer = Framework.getService(EventProducer.class);
        DocumentEventContext docCtx = new DocumentEventContext(documentManager, documentManager.getPrincipal(),
                source);
        options.put("category", RelationEvents.CATEGORY);
        options.put("comment", comment);

        try {
            evtProducer.fireEvent(docCtx.newEvent(eventId));
        } catch (ClientException e) {
            log.error("Error while trying to send notification message", e);
        }
    }

    public DocumentModel getDocumentModel(String id) throws ClientException {
        return documentManager.getDocument(new IdRef(id));
    }

    @SuppressWarnings("unchecked")
    public List<DocumentModel> getDocumentRelationSuggestions(Object input) throws ClientException {
        PageProviderService ppService = Framework.getService(PageProviderService.class);
        Map<String, Serializable> props = new HashMap<String, Serializable>();
        props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) documentManager);
        Object[] params = new Object[] { getCurrentCaseItem().getId(), input };
        PageProvider<DocumentModel> pp = (PageProvider<DocumentModel>) ppService
                .getPageProvider(CURRENT_EMAIL_RELATION_SEARCH_QUERYMODEL, null, null, null, props, params);
        return pp.getCurrentPage();
    }

    public String addStatement() throws ClientException {
        DocumentModel currentDoc = getCurrentCaseItem();
        Resource documentResource = getDocumentResource(currentDoc);
        if (documentResource == null) {
            throw new ClientException("Document resource could not be retrieved");
        }

        Resource predicate = new ResourceImpl(predicateUri);
        List<String> targetCreationDocs = getTargetCreationDocuments();
        if (targetCreationDocs == null || targetCreationDocs.isEmpty()) {
            throw new ClientException("No target documents");
        }

        Literal commentLiteral = null;
        String eventComment = null;
        if (comment != null) {
            comment = comment.trim();
            if (comment.length() > 0) {
                eventComment = comment;
                commentLiteral = new LiteralImpl(eventComment);
            }
        }

        Literal now = RelationDate.getLiteralDate(new Date());
        Literal authorLiteral = null;
        if (currentUser != null) {
            authorLiteral = new LiteralImpl(currentUser.getName());
        }

        // add statements to the graph
        List<Statement> stmts = new ArrayList<Statement>();
        String repositoryName = currentDoc.getRepositoryName();
        boolean alreadySet = false;
        boolean someSet = false;
        for (String targetDocId : targetCreationDocs) {
            String localName = repositoryName + "/" + targetDocId;
            Resource object = new QNameResourceImpl(RelationConstants.DOCUMENT_NAMESPACE, localName);

            Statement stmt = new StatementImpl(documentResource, predicate, object);

            if (commentLiteral != null) {
                stmt.addProperty(RelationConstants.COMMENT, commentLiteral);
            }
            stmt.addProperty(RelationConstants.CREATION_DATE, now);
            stmt.addProperty(RelationConstants.MODIFICATION_DATE, now);
            if (authorLiteral != null) {
                stmt.addProperty(RelationConstants.AUTHOR, authorLiteral);
            }

            if (outgoingStatements.contains(stmt)) {
                alreadySet = true;
            } else {
                someSet = true;
                stmts.add(stmt);
            }
        }

        if (someSet) {
            Map<String, Serializable> options = new HashMap<String, Serializable>();
            String currentLifeCycleState = currentDoc.getCurrentLifeCycleState();
            options.put(CoreEventConstants.DOC_LIFE_CYCLE, currentLifeCycleState);
            options.put(RelationEvents.GRAPH_NAME_EVENT_KEY, RelationConstants.GRAPH_NAME);

            // before notification
            notifyEvent(RelationEvents.BEFORE_RELATION_CREATION, currentDoc, options, eventComment);

            // add statement
            relationManager.add(RelationConstants.GRAPH_NAME, stmts);

            // after notification
            notifyEvent(RelationEvents.AFTER_RELATION_CREATION, currentDoc, options, eventComment);

            facesMessages.add(FacesMessage.SEVERITY_INFO,
                    resourcesAccessor.getMessages().get("label.relation.created"));
        }

        if (alreadySet) {
            facesMessages.add(FacesMessage.SEVERITY_WARN,
                    resourcesAccessor.getMessages().get("label.relation.already.exists"));
        }

        // make sure statements will be recomputed
        resetStatements();
        resetCreateFormValues();

        return null;
    }

    public String deleteStatement(StatementInfo stmtInfo) throws ClientException {
        if (stmtInfo != null && outgoingStatementsInfo != null && outgoingStatementsInfo.contains(stmtInfo)) {
            Statement stmt = stmtInfo.getStatement();
            // notifications
            Map<String, Serializable> options = new HashMap<String, Serializable>();
            DocumentModel source = getCurrentCaseItem();
            String currentLifeCycleState = source.getCurrentLifeCycleState();
            options.put(CoreEventConstants.DOC_LIFE_CYCLE, currentLifeCycleState);
            options.put(RelationEvents.GRAPH_NAME_EVENT_KEY, RelationConstants.GRAPH_NAME);

            // before notification
            notifyEvent(RelationEvents.BEFORE_RELATION_REMOVAL, source, options, null);

            // remove statement
            List<Statement> stmts = new ArrayList<Statement>();
            stmts.add(stmt);
            relationManager.remove(RelationConstants.GRAPH_NAME, stmts);

            // after notification
            notifyEvent(RelationEvents.AFTER_RELATION_REMOVAL, source, options, null);

            // make sure statements will be recomputed
            resetStatements();

            facesMessages.add(FacesMessage.SEVERITY_INFO,
                    resourcesAccessor.getMessages().get("label.relation.deleted"));
        }
        return null;
    }

    @Override
    protected void resetCurrentCaseItemCache(DocumentModel cachedEmail, DocumentModel newEmail)
            throws ClientException {
        resetStatements();
        resetCreateFormValues();
    }

}