I am trying to create a contentworkspaceDoc , contentWorkspaceDoc allows a document to be shared with multiple libraries. I am have a query where I pull all the existing contentworkspaceDoc from the existing documents. , I have a query where I pull the workspaces which I have want to check against.

I am trying to find for each contentworkspace , if there is a corresponding ContentworkspaceDoc with that contentworkspaceId and contentdocumentId. If Yes , do nothing , If no then create a new content workspace Doc , which allows me to share the content document Id with that contentworkspace. Below is the piece of code , I am trying to do this logic. But I am not sure , it works in some scenarios but in some scenarios it picks up the content document Id which is already shared and gives me an error. Any help or advise would be really great. Many Thanks.

 //get contentworkspace

  Map<Id, ContentWorkspace> contentWorkspaceMap = new Map<Id, ContentWorkspace>([select Id, Name from ContentWorkspace Where Name IN: UserNames ORDER BY Id DESC]);

    //Get documents from contentversions
  Map<Id, ContentVersion> contentVersionMap = new Map<Id, ContentVersion>([Select Id, ContentDocumentId, ContentDocument.ParentId from ContentVersion where IsLatest = true AND (record__c IN: dealRecordMap.keySet() OR agreement__c IN: agreementMap.keySet())]);

            set<Id> documentIds = new set<Id>();
            for(contentVersion cvValue :  contentVersionMap.values()){
            //get all documents

  Map<Id, ContentDocument> cDocumentsMap = new Map<Id, ContentDocument>([Select Id from ContentDocument where Id IN: documentIds]);

    // get all contentworkspacedoc for which have contentdocumentId in those documentIds set.

 Map<Id, ContentworkspaceDoc> cwSpaceDocMap = new Map<Id, ContentWorkspaceDoc>();

 Map<Id, Id> bigMap;

 for(contentWorkspaceDoc cwSpaceDoc : [select  Id , contentDocumentId,  contentWorkspaceId from ContentWorkspaceDoc where contentDocumentId IN: documentIds and isOwner = false ORDER BY contentWorkspaceId ASC])

     cwSpaceDocMap.put(cwSpaceDoc.Id, cwSpaceDoc);
     bigMap = new Map<Id,Id>{cwSpaceDoc.ContentWorkspaceId =>    cwSpaceDoc.ContentDocumentId};

    Map<Id, contentworkspaceDoc> cwDocNewMap = new Map<Id, contentWorkspaceDoc>();
            for(Id cwId1 : contentWorkspaceMap.keySet()){
                system.debug('entered 1st loop');
                for(contentWorkspaceDoc spaceDoc1 : cwSpaceDocMap.values()){
                    system.debug('cwSpaceDocMap '+ cwSpaceDocMap.size());
                    system.debug('spaceDoc1'+ spaceDoc1.contentWorkspaceId);
                    system.debug('cwId1'+ cwId1);
                    system.debug('content document Id' + spaceDoc1.ContentDocumentId);
                    if(spaceDoc1.contentWorkspaceId == cwId1){

                        ContentWorkspaceDoc cwdoc = new ContentWorkspaceDoc();
                        cwDoc.ContentDocumentId = spaceDoc1.contentDocumentId;
                        cwDoc.ContentWorkspaceId = cwId1;
                        cwTocwDocMap.put(cwId1, cwDoc);
                     //   break;


Thank You

  • and the error you get is? (You might also want to reformat your code to be reasonably indented
    – cropredy
    Commented Mar 19, 2015 at 16:23
  • Thank You for the reply. Yes, I will format .. the indentation went wrong in copy and paste here. The error I get is that , It is inserting a document which is already being shared with the workspace with whom I am trying to share.
    – user2551
    Commented Mar 19, 2015 at 17:24
  • uh -- your formatting is even worse -- use the {} button to make it look like code and then adjust within
    – cropredy
    Commented Mar 19, 2015 at 18:04
  • Apologise, reformatted it again !!!
    – user2551
    Commented Mar 19, 2015 at 18:13

1 Answer 1


I took a stab at this (using some different variable names that follow conventions I use) and removed some noise to improve clarity.

  • CWS = ContentWorkSpace

  • CV = ContentVersion

  • CWSD = ContentWorskpaceDocument - the junction record that does the sharing

  • CD = ContentDocument

     ContentWorkspaceDoc[] cwsdInsList = new List<ContentWorkspaceDoc>();
     // 1. Get all CWS that new CVs must be shared to
     Map<ID,ContentWorkspace> cwsIdToContentWorkspaceMap = ... (as you have it)
     // 2. Get all CVs that require sharing 
     Map<ID,ContentVersion> cvIdToContentVersionMap = ... (as you have it)
     // 3. Get all CDs of CVs that require sharing .. CD.id is part of the CWSD junction rec
     set<Id> documentIds = new set<Id>();
     for(contentVersion cv :  contentVersionMap.values()){
     Map<ID,ContentDocument> cdIdToContentDocumentMap = ... (as you have it) 
     // 4. For all ContentDocs, see if shared to each ContentWorkspace
     //    Go through each existing share
     for (ContentWorkspaceDoc cwsd : [select id, contentDocumentId, contentWorkspaceId 
                                        from ContentWorkspaceDoc 
                                        where contentDocumentId IN: documentIds] ) {
       // go through each CWS and if no match, add to insert list
       for (Id cwsId : cwsIdToContentWorkspaceMap.keySet() )
           if (cwsd.contentWorkspaceId == cwsId) continue;  // already shared
           cwsdInsList.add(new ContentWorkspaceDoc(
                                  contentDocumentId = cwsd.contentDocumentId,
                                  contentWorkspaceId = cwsd.id); // share it
     insert cwsdInsList; 

There is probably a more efficient way to do this but it should compare existing shares (CWSDs) to all possible libraries (CWS) and add to the insert list when no match is found

Note that testing anything with ContentWorkspace must be done either with

  • SeeAllData=true as you can't DML mock libraries (ugh)
  • Replacing your SOQL with selector classes, and your DML with UnitofWork pattern and using a mocking framework like ApexMocks or Amoss to mock the selector/unitOfWork

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .