cancel
Showing results for 
Search instead for 
Did you mean: 

Copy folder (including aspects) using CMIS

mikemars
Champ in-the-making
Champ in-the-making
Hello,

I'd like to be able to copy and paste an Alfresco folder using OpenCMIS. Currently the best way I can find to do this is to use the createFolder(Map<String, ?> properties) method found in the Folder class. I populate the copied folders name in the map of properties.

What this method doesn't account for is copying any aspects which are applied on the copied folder. I could look up the aspects on the copied folder and apply them to the newly created folder, but this may result in applying aspects which shouldn't be included when performing a copy command.

Is there any way within cmis to copy a folder and include aspects from the copied folder?

Thanks.
5 REPLIES 5

zuzoovn
Champ in-the-making
Champ in-the-making
Hi, could you please share your method to "copy and paste an Alfresco folder using OpenCMIS"
I am making android client

Regadrs

mikemars
Champ in-the-making
Champ in-the-making
Sure,

Here is a simplified version of what I have, but you will get the idea:

You will have two folder objects, the one you have copied (toCopyFolder) and the destination folder where you are copying to (parentFolder).


   
   public void copyFolder(Folder parentFolder, Folder toCopyFolder) {

      Map<String, Object> folderProperties = new HashMap<String, Object>(2);
      folderProperties.put(PropertyIds.NAME, toCopyFolder.getName());
      folderProperties.put(PropertyIds.OBJECT_TYPE_ID, toCopyFolder.getBaseTypeId().value());

      Folder newFolder = parentFolder.createFolder(properties);

      copyChildren(newFolder, toCopyFolder);
  }
 
  public void copyChildren(Folder parentFolder, Folder toCopyFolder) {

     ItemIterable<CmisObject> immediateChildren = toCopyFolder.getChildren();

     for (CmisObject child : immediateChildren) {
        if (child instanceof Document) {
           copyDocument(parentFolder, (Document) child)
        } else if (child instanceof Folder) {
           copyFolder(parentFolder, (Folder) child)
        }
     }
  }

  public void copyDocument(Folder parentFolder, Document toCopyDocument) {
      Map<String, Object> documentProperties = new HashMap<String, Object>(2);
      documentProperties.put(PropertyIds.NAME, toCopyDocument.getName());
      documentProperties.put(PropertyIds.OBJECT_TYPE_ID, toCopyDocument.getBaseTypeId().value());

      sourceDocument.copy(parentFolder, documentProperties , null, null, null, null, null);
  }


As I said in my first post though, the folders themselves aren't really a copy of the originals, they are just new folders which have the same name.

Hope that helps you get started.

Thanks for the code, very useful. I found that adding a couple of extra lines to the copyDocument method let me copy aspects as well (although I'm very new to Alfresco and CMIS so it's possible I've missed something!):

<java>
    public static Folder copyFolder(Folder parentFolder,
                Folder toCopyFolder,
                String newFolderName) {
   Map<String, Object> folderProperties = new HashMap<String, Object>(2);
   folderProperties.put(PropertyIds.NAME, newFolderName);
   folderProperties.put(PropertyIds.OBJECT_TYPE_ID,
              toCopyFolder.getBaseTypeId().value());

   Folder newFolder = parentFolder.createFolder(folderProperties);

   copyChildren(newFolder, toCopyFolder);
   return newFolder;
    }

    public static void copyChildren(Folder parentFolder, Folder toCopyFolder) {

   ItemIterable<CmisObject> immediateChildren = toCopyFolder.getChildren();

   for (CmisObject child : immediateChildren) {
       if (child instanceof Document)
      copyDocument(parentFolder, (Document) child);
       else if (child instanceof Folder)
      copyFolder(parentFolder, (Folder) child, child.getName());
   }
    }

    public static void copyDocument(Folder parentFolder, Document toCopyDocument) {
   Map<String, Object> documentProperties = new HashMap<String, Object>(2);

   documentProperties.put(PropertyIds.NAME, toCopyDocument.getName());

   // Retrieve aspects for this document - NEW
   Iterator<ObjectType> aspects = ((AlfrescoDocument)toCopyDocument).getAspects().iterator();
   String aspectIds = "";
   while (aspects.hasNext()) {
       aspectIds += ',';
       aspectIds += aspects.next().getId();
   }
   documentProperties.put(PropertyIds.OBJECT_TYPE_ID,
                toCopyDocument.getBaseTypeId().value() + aspectIds);

   toCopyDocument.copy(parentFolder, documentProperties, null, null, null,
             null, null);
  }
</java>

Thanks for the suggestion.

The issue I have is with copying aspects applied directly to folders rather to documents. In your example above, you shouldn't need to add the new code for documents, as the aspects are copied over by Alfresco.

You can use that technique to apply aspects to folders, but the problem is that it effectively bypasses any behaviours which decide whether an aspect should be copied or not. As I do have behaviours which block aspects being copied in certain situations, I can't go down this route.

Hope that makes sense.

rahulalfresco
Champ in-the-making
Champ in-the-making
Hi,

While using document copy.. i am getting below error.. can anyone help me in this.. And one more observation sometimes it works!!

org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException: Cannot access http://localhost:8080/alfresco/cmisatom/43f0961b-63a3-400d-a459-2c290edf03ae/children?id=de2b7a31-40...: Software caused connection abort: recv failed
   at org.apache.chemistry.opencmis.client.bindings.spi.http.DefaultHttpInvoker.invoke(DefaultHttpInvoker.java:224)
   at org.apache.chemistry.opencmis.client.bindings.spi.http.DefaultHttpInvoker.invokePOST(DefaultHttpInvoker.java:63)
   at org.apache.chemistry.opencmis.client.bindings.spi.atompub.AbstractAtomPubService.post(AbstractAtomPubService.java:625)
   at org.apache.chemistry.opencmis.client.bindings.spi.atompub.ObjectServiceImpl.createDocument(ObjectServiceImpl.java:119)
   at org.apache.chemistry.opencmis.client.runtime.SessionImpl.createDocument(SessionImpl.java:751)
   at org.apache.chemistry.opencmis.client.runtime.DocumentImpl.copyViaClient(DocumentImpl.java:207)
   at org.apache.chemistry.opencmis.client.runtime.DocumentImpl.copy(DocumentImpl.java:155)
   at test.com.se.dce.spim.CopyObjectService.copyObject(CopyObjectService.java:82)
   at test.com.se.dce.spim.CopyObjectService.main(CopyObjectService.java:46)
Caused by: java.net.SocketException: Software caused connection abort: recv failed
   at java.net.SocketInputStream.socketRead0(Native Method)
   at java.net.SocketInputStream.read(SocketInputStream.java:152)
   at java.net.SocketInputStream.read(SocketInputStream.java:122)
   at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
   at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
   at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
   at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:687)
   at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
   at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1323)
   at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
   at org.apache.chemistry.opencmis.client.bindings.spi.http.DefaultHttpInvoker.invoke(DefaultHttpInvoker.java:204)