<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: What is the most efficient way to follow a chain of document relations? in Nuxeo Forum</title>
    <link>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322070#M9071</link>
    <description>&lt;P&gt;I should clarify that I don't need the file content for all documents in the single response, but only the Document entries as they appear in the response to &lt;CODE&gt;Relations.GetRelations&lt;/CODE&gt;.&lt;/P&gt;</description>
    <pubDate>Tue, 03 Mar 2015 14:25:02 GMT</pubDate>
    <dc:creator>Steven_Huwig1</dc:creator>
    <dc:date>2015-03-03T14:25:02Z</dc:date>
    <item>
      <title>What is the most efficient way to follow a chain of document relations?</title>
      <link>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322069#M9070</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;
&lt;P&gt;I am considering a repository structure where there are two document types: let's call one "Base" and the other "Enhancements". I would like to use the Relations functionality of Nuxeo to indicated that a given "Enhancements" requires a given "Base" using the standard Dublin Core relation included with the software.&lt;/P&gt;
&lt;P&gt;This is working fine, and I am able to find the Base documents from the Enhancements documents that require them programmatically using the &lt;CODE&gt;Relations.GetRelations&lt;/CODE&gt; operation. However, this only traverses one edge of the given relation. Is there already a way in Nuxeo to retrieve both documents "EnhancementsB" and "Base" in the following dependency chain, if I am querying the "EnhancementsA" document?&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;EnhancementsA ---requires--&amp;gt; EnhancementsB ---requires--&amp;gt; Base
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Obviously I could take the output I have and query the document it returns, but my goal is to reduce the number of serial web requests needed to acquire this information, since the ultimate request is coming from a mobile client. I could also define a server-side operation to go through a fixed number of such relation edges, but maybe there is a better way?&lt;/P&gt;
&lt;P&gt;Thanks for any help.&lt;/P&gt;</description>
      <pubDate>Mon, 02 Mar 2015 21:56:58 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322069#M9070</guid>
      <dc:creator>Steven_Huwig1</dc:creator>
      <dc:date>2015-03-02T21:56:58Z</dc:date>
    </item>
    <item>
      <title>Re: What is the most efficient way to follow a chain of document relations?</title>
      <link>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322070#M9071</link>
      <description>&lt;P&gt;I should clarify that I don't need the file content for all documents in the single response, but only the Document entries as they appear in the response to &lt;CODE&gt;Relations.GetRelations&lt;/CODE&gt;.&lt;/P&gt;</description>
      <pubDate>Tue, 03 Mar 2015 14:25:02 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322070#M9071</guid>
      <dc:creator>Steven_Huwig1</dc:creator>
      <dc:date>2015-03-03T14:25:02Z</dc:date>
    </item>
    <item>
      <title>Re: What is the most efficient way to follow a chain of document relations?</title>
      <link>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322071#M9072</link>
      <description>&lt;P&gt;I ended up implementing the following solution. It appears to work for my use case.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;package com.example;

import org.apache.commons.lang.StringUtils;
import org.nuxeo.ecm.automation.core.Constants;
import org.nuxeo.ecm.automation.core.annotations.Context;
import org.nuxeo.ecm.automation.core.annotations.Operation;
import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
import org.nuxeo.ecm.automation.core.annotations.Param;
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.DocumentModelList;
import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
import org.nuxeo.ecm.platform.relations.api.Graph;
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.impl.ResourceImpl;
import org.nuxeo.ecm.platform.relations.api.util.RelationConstants;

import java.util.Collections;
import java.util.List;
import java.util.Map;

@Operation(id = GetAllLinkedDocuments.ID, category = Constants.CAT_SERVICES, label = "Get All Linked Documents", description = "Get all documents related to the input document.  Includes the input document and any linked documents found via recursive relation search.")
public class GetAllLinkedDocuments {
    public static final String ID = "Example.Document.GetAllLinkedDocuments";

    @Context
    protected CoreSession session;

    @Context
    protected RelationManager relations;

    @Param(name = "predicate")
    protected String predicate;

    @Param(name = "graphName", required = false)
    protected String graphName;

    @OperationMethod
    public DocumentModelList run(DocumentModel doc) throws Exception {
        Resource pred = new ResourceImpl(predicate);
        Graph graph = relations.getGraphByName(getGraphName());
        DocumentModelList result = new DocumentModelListImpl();
        depthFirstSearch(graph, pred, doc, result);
        return result;
    }

    private void depthFirstSearch(Graph graph, Resource pred,
                                  DocumentModel doc,
                                  DocumentModelList found) {
        found.add(doc);
        for (DocumentModel relatedDoc : getRelatedDocs(graph, pred, doc)) {
            if (!found.contains(relatedDoc)) {
                depthFirstSearch(graph, pred, relatedDoc, found);
            }
        }
    }

    private DocumentModelList getRelatedDocs(Graph graph, Resource pred,
                                             DocumentModel doc) {
        QNameResource resource = (QNameResource) relations.getResource(
                RelationConstants.DOCUMENT_NAMESPACE, doc, null);
        List&amp;lt;Statement&amp;gt; statements = graph.getStatements(resource, pred, null);
        DocumentModelList docs = new DocumentModelListImpl(statements.size());
        for (Statement st : statements) {
            DocumentModel dm = getDocumentModel(st.getObject());
            if (dm != null) {
                docs.add(dm);
            }
        }
        return docs;
    }

    // copied from org.nuxeo.ecm.automation.core.operations.services.GetRelations
    protected DocumentModel getDocumentModel(Node node) throws
            ClientException {
        if (node.isQNameResource()) {
            QNameResource resource = (QNameResource) node;
            Map&amp;lt;String, Object&amp;gt; context = Collections.&amp;lt;String, Object&amp;gt; singletonMap(
                    ResourceAdapter.CORE_SESSION_CONTEXT_KEY, session);
            Object o = relations.getResourceRepresentation(
                    resource.getNamespace(), resource, context);
            if (o instanceof DocumentModel) {
                return (DocumentModel) o;
            }
        }
        return null;
    }

    // copied from org.nuxeo.ecm.automation.core.operations.services.GetRelation
    public String getGraphName() {
        if (StringUtils.isEmpty(graphName)) {
            return RelationConstants.GRAPH_NAME;
        }
        return graphName;
    }

}
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Fri, 13 Mar 2015 21:10:50 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322071#M9072</guid>
      <dc:creator>Steven_Huwig1</dc:creator>
      <dc:date>2015-03-13T21:10:50Z</dc:date>
    </item>
    <item>
      <title>Re: What is the most efficient way to follow a chain of document relations?</title>
      <link>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322072#M9073</link>
      <description>&lt;P&gt;Instead of creating getRelatedDocs and copying the methods getDocumentModel and getGraphName, why not use the corresponding operation (Relations.GetRelations) ? Is there any performance issue?&lt;/P&gt;
&lt;P&gt;For example, something like this (not tested):&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;private void depthFirstSearch(Graph graph, Resource pred,
                              DocumentModel doc,
                              DocumentModelList found) {
                              
	OperationContext ctx = new OperationContext(session);
	ctx.setInput(doc);

	Map&amp;lt;String, Object&amp;gt; params = new HashMap&amp;lt;String, Object&amp;gt;();
	params.put("predicate", "http://purl.org/dc/terms/References");
	params.put("outgoing", true);

	AutomationService service = Framework.getService(AutomationService.class);
     
    found.add(doc);
    for (DocumentModel relatedDoc : (DocumentModelList)service.run(ctx, "Relations.GetRelations", params)) {
        if (!found.contains(relatedDoc)) {
            depthFirstSearch(graph, pred, relatedDoc, found);
        }
    }
}
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Mon, 16 Mar 2015 13:00:03 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322072#M9073</guid>
      <dc:creator>ioihanguren_</dc:creator>
      <dc:date>2015-03-16T13:00:03Z</dc:date>
    </item>
    <item>
      <title>Re: What is the most efficient way to follow a chain of document relations?</title>
      <link>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322073#M9074</link>
      <description>&lt;P&gt;That looks like it would work in principle. I did notice that they were renaming the GetRelations/CreateRelation operation in the fasttrack release though.&lt;/P&gt;</description>
      <pubDate>Mon, 16 Mar 2015 13:53:16 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/nuxeo-forum/what-is-the-most-efficient-way-to-follow-a-chain-of-document/m-p/322073#M9074</guid>
      <dc:creator>Steven_Huwig1</dc:creator>
      <dc:date>2015-03-16T13:53:16Z</dc:date>
    </item>
  </channel>
</rss>

