@Test
  public void canLogMultipleLifecycleTransitionsInSameTx() throws ClientException {
    // generate events
    DocumentModel doc = repo.createDocumentModel("/", "a-file", "File");
    doc = repo.createDocument(doc);
    String initialLifeCycle = doc.getCurrentLifeCycleState();
    doc.followTransition(LifeCycleConstants.DELETE_TRANSITION);
    String deletedLifeCycle = doc.getCurrentLifeCycleState();
    doc.followTransition(LifeCycleConstants.UNDELETE_TRANSITION);
    String undeletedLifeCycle = doc.getCurrentLifeCycleState();
    TransactionHelper.commitOrRollbackTransaction();
    Framework.getLocalService(EventService.class).waitForAsyncCompletion();

    // test audit trail
    AuditReader reader = Framework.getLocalService(AuditReader.class);
    List<LogEntry> trail = reader.getLogEntriesFor(doc.getId());

    assertThat(trail, notNullValue());
    assertThat(trail.size(), is(3));

    boolean seenDocCreated = false;
    boolean seenDocDeleted = false;
    boolean seenDocUndeleted = false;

    for (LogEntry entry : trail) {
      String lifeCycle = entry.getDocLifeCycle();
      String id = entry.getEventId();
      if (DocumentEventTypes.DOCUMENT_CREATED.equals(id)) {
        if (initialLifeCycle.equals(lifeCycle)) {
          seenDocCreated = true;
        }
      } else if (LifeCycleConstants.TRANSITION_EVENT.equals(id)) {
        if (undeletedLifeCycle.equals(lifeCycle)) {
          seenDocUndeleted = true;
        } else if (deletedLifeCycle.equals(lifeCycle)) {
          seenDocDeleted = true;
        }
      }
    }

    assertThat(seenDocUndeleted, is(true));
    assertThat(seenDocDeleted, is(true));
    assertThat(seenDocCreated, is(true));
  }
 @Override
 protected void fillPart(
     PayloadInputPart part,
     DocumentModel docModel,
     ObjectPartType partMeta,
     Action action,
     ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx)
     throws Exception {
   WorkflowCommon workflowsCommon = (WorkflowCommon) part.getBody();
   docModel.followTransition(getTransitionFromState(workflowsCommon.getCurrentLifeCycleState()));
 }
  @Test
  public void testTransitionProxy() throws Exception {
    DocumentModel root = session.getRootDocument();
    DocumentModel doc = new DocumentModelImpl("/", "doc", "File");

    doc = session.createDocument(doc);
    doc.setProperty("dublincore", "title", "t1");
    doc = session.saveDocument(doc);

    DocumentModel proxy = session.publishDocument(doc, root);
    session.save();

    Collection<String> transitions = proxy.getAllowedStateTransitions();
    assertEquals(3, transitions.size());

    if (proxy.getAllowedStateTransitions().contains("delete")) {
      proxy.followTransition("delete");
    }
    assertEquals("deleted", proxy.getCurrentLifeCycleState());
  }
  @Test
  public void testVersionLifecycle() throws Exception {
    DocumentModel root = session.getRootDocument();
    DocumentModel doc = new DocumentModelImpl("/", "doc", "File");

    doc = session.createDocument(doc);
    doc.setProperty("dublincore", "title", "t1");
    doc = session.saveDocument(doc);

    session.publishDocument(doc, root);
    session.save();

    // get version
    DocumentModel ver = session.getLastDocumentVersion(doc.getRef());
    assertTrue(ver.isVersion());

    assertEquals("project", ver.getCurrentLifeCycleState());
    ver.followTransition("approve");
    session.save();

    doc = session.getDocument(new PathRef("/doc"));
    ver = session.getLastDocumentVersion(doc.getRef());
    assertEquals("approved", ver.getCurrentLifeCycleState());
  }
  @Test
  public void testLiveProxyUpdate() throws Exception {
    DocumentModel section = session.createDocumentModel("/", "section", "Folder");
    section = session.createDocument(section);
    DocumentModel doc = session.createDocumentModel("/", "file", "File");
    doc = session.createDocument(doc);
    session.save();

    // create a live proxy
    DocumentModel proxy = session.createProxy(doc.getRef(), section.getRef());

    // --- change the doc, see changes on the proxy immediately without save ---

    // update
    doc.setPropertyValue("dc:title", "foo");
    doc = session.saveDocument(doc);
    assertEquals("foo", doc.getPropertyValue("dc:title"));
    // visible immediately on the proxy
    proxy.refresh();
    assertEquals("foo", proxy.getPropertyValue("dc:title"));

    // lifecycle change
    doc.followTransition("approve");
    assertEquals("approved", doc.getCurrentLifeCycleState());
    // visible immediately on the proxy
    proxy.refresh();
    assertEquals("approved", proxy.getCurrentLifeCycleState());

    // check in for version change
    doc.checkIn(VersioningOption.MINOR, null);
    assertFalse(doc.isCheckedOut());
    assertEquals("0.1", doc.getVersionLabel());
    // visible immediately on the proxy
    proxy.refresh();
    assertFalse(proxy.isCheckedOut());
    assertEquals("0.1", proxy.getVersionLabel());

    // check out
    doc.checkOut();
    assertTrue(doc.isCheckedOut());
    assertEquals("0.1+", doc.getVersionLabel());
    // visible immediately on the proxy
    proxy.refresh();
    assertTrue(proxy.isCheckedOut());
    assertEquals("0.1+", proxy.getVersionLabel());

    // --- change the proxy, see changes on the doc immediately without save ---

    // update
    proxy.setPropertyValue("dc:title", "bar");
    proxy = session.saveDocument(proxy);
    assertEquals("bar", proxy.getPropertyValue("dc:title"));
    // visible immediately on the doc, no save() needed
    doc.refresh();
    assertEquals("bar", doc.getPropertyValue("dc:title"));

    // lifecycle change
    proxy.followTransition("backToProject");
    assertEquals("project", proxy.getCurrentLifeCycleState());
    // visible immediately on the doc
    doc.refresh();
    assertEquals("project", doc.getCurrentLifeCycleState());

    // check in for version change
    proxy.checkIn(VersioningOption.MINOR, null);
    assertFalse(proxy.isCheckedOut());
    assertEquals("0.2", proxy.getVersionLabel());
    // visible immediately on the doc
    doc.refresh();
    assertFalse(doc.isCheckedOut());
    assertEquals("0.2", doc.getVersionLabel());

    // check out
    proxy.checkOut();
    assertTrue(proxy.isCheckedOut());
    assertEquals("0.2+", proxy.getVersionLabel());
    // visible immediately on the doc
    doc.refresh();
    assertTrue(doc.isCheckedOut());
    assertEquals("0.2+", doc.getVersionLabel());
  }
  @Test
  public void documentManagementInTestCasesExample() throws ClientException {
    SchemaManager typeService = Framework.getLocalService(SchemaManager.class);

    DocumentType[] types = typeService.getDocumentTypes();
    for (DocumentType type : types) {
      System.out.println(type.getName());
    }

    DocumentModel mydoc = session.createDocumentModel("File");
    // DocumentModel mydoc = session.createDocumentModel("/", "toto",
    // "File");

    mydoc.setPathInfo("/", "toto");
    mydoc.setPropertyValue("dc:title", "Toto");
    mydoc = session.createDocument(mydoc);
    session.save();

    DocumentModelList docs = session.query("SELECT * FROM Document WHERE dc:title = 'Toto'");
    assertEquals(1, docs.size());
    mydoc = docs.get(0);
    assertEquals("toto", mydoc.getName());
    assertEquals("project", mydoc.getCurrentLifeCycleState());

    for (String state : mydoc.getAllowedStateTransitions()) {
      System.out.println("Transition : " + state);
    }

    // session.followTransition(mydoc.getRef(), "approve");
    mydoc.followTransition("approve");

    mydoc.setPropertyValue("dc:description", "My Description");
    mydoc = session.saveDocument(mydoc);
    session.save();

    assertEquals("approved", mydoc.getCurrentLifeCycleState());
    assertEquals("0.0", mydoc.getVersionLabel());
    assertEquals(0, session.getVersions(mydoc.getRef()).size());

    session.checkIn(mydoc.getRef(), VersioningOption.MINOR, "");
    mydoc = session.getDocument(mydoc.getRef());
    assertEquals("0.1", mydoc.getVersionLabel());
    assertEquals(1, session.getVersions(mydoc.getRef()).size());

    DocumentModel folder = session.createDocumentModel("/", "folder", "Folder");
    folder.setPropertyValue("dc:title", "Folder");
    folder = session.createDocument(folder);
    session.save();

    assertEquals(0, session.getChildren(folder.getRef()).size());
    session.publishDocument(mydoc, folder);
    assertEquals(1, session.getChildren(folder.getRef()).size());

    DocumentModel folder2 = session.createDocumentModel("/", "folder2", "Folder");
    folder2.setPropertyValue("dc:title", "Folder2");
    folder2 = session.createDocument(folder2);
    session.save();

    DocumentModel proxy = session.createProxy(mydoc.getRef(), folder2.getRef());

    assertEquals("Toto", proxy.getPropertyValue("dc:title"));
    mydoc.setPropertyValue("dc:title", "Tutu");
    session.saveDocument(mydoc);
    session.save();

    proxy = session.getDocument(proxy.getRef());
    assertEquals("Tutu", proxy.getPropertyValue("dc:title"));

    proxy.setPropertyValue("dc:title", "Tata");
    session.saveDocument(proxy);
    session.save();

    mydoc = session.getDocument(mydoc.getRef());
    assertEquals("Tata", mydoc.getPropertyValue("dc:title"));
  }
  @Test
  public void testReadOperations() throws Exception {

    // ------------------------------------------------------
    // Check #getTopLevelFolder
    // ------------------------------------------------------
    List<FileSystemItem> topLevelChildren =
        fileSystemItemManagerService.getTopLevelFolder(principal).getChildren();
    assertNotNull(topLevelChildren);
    assertEquals(2, topLevelChildren.size());

    FileSystemItem childFsItem = topLevelChildren.get(0);
    assertTrue(childFsItem instanceof DefaultSyncRootFolderItem);
    assertEquals("defaultSyncRootFolderItemFactory#test#" + syncRoot1.getId(), childFsItem.getId());
    assertTrue(childFsItem.getParentId().endsWith("DefaultTopLevelFolderItemFactory#"));
    assertEquals("syncRoot1", childFsItem.getName());

    childFsItem = topLevelChildren.get(1);
    assertTrue(childFsItem instanceof DefaultSyncRootFolderItem);
    assertEquals("defaultSyncRootFolderItemFactory#test#" + syncRoot2.getId(), childFsItem.getId());
    assertTrue(childFsItem.getParentId().endsWith("DefaultTopLevelFolderItemFactory#"));
    assertEquals("syncRoot2", childFsItem.getName());

    // ------------------------------------------------------
    // Check #exists
    // ------------------------------------------------------
    // Non existent doc id
    assertFalse(
        fileSystemItemManagerService.exists(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + "nonExistentId", principal));
    // File
    assertTrue(
        fileSystemItemManagerService.exists(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + file.getId(), principal));
    // Not adaptable as a FileSystemItem
    assertFalse(
        fileSystemItemManagerService.exists(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + notAFileSystemItem.getId(), principal));
    // Deleted
    custom.followTransition("delete");
    assertFalse(
        fileSystemItemManagerService.exists(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + custom.getId(), principal));

    // ------------------------------------------------------------
    // Check #getFileSystemItemById(String id, Principal principal)
    // ------------------------------------------------------------
    // Folder
    FileSystemItem fsItem =
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), principal);
    assertNotNull(fsItem);
    assertTrue(fsItem instanceof FolderItem);
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), fsItem.getId());
    String expectedSyncRoot1Id = DEFAULT_SYNC_ROOT_ITEM_ID_PREFIX + syncRoot1.getId();
    assertEquals(expectedSyncRoot1Id, fsItem.getParentId());
    assertEquals("Jack's folder", fsItem.getName());
    assertTrue(fsItem.isFolder());
    assertTrue(fsItem.getCanRename());
    assertTrue(fsItem.getCanDelete());
    assertTrue(((FolderItem) fsItem).getCanCreateChild());
    List<FileSystemItem> children = ((FolderItem) fsItem).getChildren();
    assertNotNull(children);
    assertEquals(4, children.size());

    // File
    fsItem =
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + file.getId(), principal);
    assertNotNull(fsItem);
    assertTrue(fsItem instanceof FileItem);
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + file.getId(), fsItem.getId());
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), fsItem.getParentId());
    assertEquals("Joe.odt", fsItem.getName());
    assertFalse(fsItem.isFolder());
    assertTrue(fsItem.getCanRename());
    assertTrue(fsItem.getCanDelete());
    FileItem fileFsItem = (FileItem) fsItem;
    assertTrue(fileFsItem.getCanUpdate());
    assertEquals(
        "nxfile/test/" + file.getId() + "/blobholder:0/Joe.odt", fileFsItem.getDownloadURL());
    assertEquals("MD5", fileFsItem.getDigestAlgorithm());
    assertEquals(file.getAdapter(BlobHolder.class).getBlob().getDigest(), fileFsItem.getDigest());
    Blob fileItemBlob = fileFsItem.getBlob();
    assertEquals("Joe.odt", fileItemBlob.getFilename());
    assertEquals("Content of Joe's file.", fileItemBlob.getString());

    // FolderishFile
    fsItem =
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folderishFile.getId(), principal);
    assertNotNull(fsItem);
    assertTrue(fsItem instanceof FolderItem);
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folderishFile.getId(), fsItem.getId());
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), fsItem.getParentId());
    assertEquals("Sarah's folderish file", fsItem.getName());
    assertTrue(fsItem.isFolder());
    assertTrue(fsItem.getCanRename());
    assertTrue(fsItem.getCanDelete());
    assertTrue(((FolderItem) fsItem).getCanCreateChild());
    assertTrue(((FolderItem) fsItem).getChildren().isEmpty());

    // Not adaptable as a FileSystemItem
    fsItem =
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + notAFileSystemItem.getId(), principal);
    assertNull(fsItem);

    // Deleted
    assertNull(
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + custom.getId(), principal));

    // Sub folder
    fsItem =
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + subFolder.getId(), principal);
    assertNotNull(fsItem);
    assertTrue(fsItem instanceof FolderItem);
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + subFolder.getId(), fsItem.getId());
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), fsItem.getParentId());
    assertEquals("Tony's sub folder", fsItem.getName());
    assertTrue(fsItem.isFolder());
    assertTrue(fsItem.getCanRename());
    assertTrue(fsItem.getCanDelete());
    assertTrue(((FolderItem) fsItem).getCanCreateChild());
    assertTrue(((FolderItem) fsItem).getChildren().isEmpty());

    // -------------------------------------------------------------------
    // Check #getFileSystemItemById(String id, String parentId, Principal
    // principal)
    // -------------------------------------------------------------------
    fsItem =
        fileSystemItemManagerService.getFileSystemItemById(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + file.getId(),
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(),
            principal);
    assertTrue(fsItem instanceof FileItem);
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + file.getId(), fsItem.getId());
    assertEquals(DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), fsItem.getParentId());

    // ------------------------------------------------------
    // Check #getChildren
    // ------------------------------------------------------
    // Need to flush VCS cache for the session used in DocumentBackedFolderItem#getChildren() to be
    // aware of changes
    // in the current session
    session.save();
    children =
        fileSystemItemManagerService.getChildren(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), principal);
    assertNotNull(children);

    assertEquals(4, children.size());
    // Ordered
    checkChildren(
        children,
        folder.getId(),
        file.getId(),
        note.getId(),
        folderishFile.getId(),
        subFolder.getId(),
        true);

    children =
        fileSystemItemManagerService.getChildren(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + subFolder.getId(), principal);
    assertTrue(children.isEmpty());

    // ------------------------------------------------------
    // Check #scrollDescendants
    // ------------------------------------------------------
    // Need to flush VCS cache for the session used in DocumentBackedFolderItem#scrollDescendants to
    // be aware of
    // changes in the current session
    session.save();
    FolderItem folderItem =
        (FolderItem)
            fileSystemItemManagerService.getFileSystemItemById(
                DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), principal);
    assertTrue(folderItem.getCanScrollDescendants());

    // Scroll through all descendants in one breath
    ScrollFileSystemItemList folderDescendants =
        fileSystemItemManagerService.scrollDescendants(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + folder.getId(), principal, null, 10, 1000);
    assertNotNull(folderDescendants);
    assertNotNull(folderDescendants.getScrollId());
    assertEquals(4, folderDescendants.size());
    // Order is not determined
    checkChildren(
        folderDescendants,
        folder.getId(),
        file.getId(),
        note.getId(),
        folderishFile.getId(),
        subFolder.getId(),
        false);

    // Scroll through descendants in several steps
    folderDescendants.clear();
    ScrollFileSystemItemList descendantsBatch;
    int batchSize = 2;
    String scrollId = null;
    while (!(descendantsBatch = folderItem.scrollDescendants(scrollId, batchSize, 1000))
        .isEmpty()) {
      assertTrue(descendantsBatch.size() > 0);
      scrollId = descendantsBatch.getScrollId();
      folderDescendants.addAll(descendantsBatch);
    }
    assertEquals(4, folderDescendants.size());
    // Order is not determined
    checkChildren(
        folderDescendants,
        folder.getId(),
        file.getId(),
        note.getId(),
        folderishFile.getId(),
        subFolder.getId(),
        false);

    folderDescendants =
        fileSystemItemManagerService.scrollDescendants(
            DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + subFolder.getId(), principal, null, 10, 1000);
    assertTrue(folderDescendants.isEmpty());

    // ------------------------------------------------------
    // Check #canMove
    // ------------------------------------------------------
    // Not allowed to move a file system item to a non FolderItem
    String srcFsItemId = DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + note.getId();
    String destFsItemId = DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + file.getId();
    assertFalse(fileSystemItemManagerService.canMove(srcFsItemId, destFsItemId, principal));

    // Not allowed to move a file system item if no REMOVE permission on the
    // source backing doc
    Principal joePrincipal = new NuxeoPrincipalImpl("joe");
    DocumentModel rootDoc = session.getRootDocument();
    setPermission(rootDoc, "joe", SecurityConstants.READ, true);
    nuxeoDriveManager.registerSynchronizationRoot(joePrincipal, syncRoot1, session);

    // Under Oracle, the READ ACL optims are not visible from the joe
    // session while the transaction has not been committed.
    TransactionHelper.commitOrRollbackTransaction();
    TransactionHelper.startTransaction();

    destFsItemId = DEFAULT_FILE_SYSTEM_ITEM_ID_PREFIX + subFolder.getId();
    assertFalse(fileSystemItemManagerService.canMove(srcFsItemId, destFsItemId, joePrincipal));

    // Not allowed to move a file system item if no ADD_CHILDREN permission
    // on the destination backing doc
    setPermission(folder, "joe", SecurityConstants.WRITE, true);
    setPermission(subFolder, "joe", SecurityConstants.READ, true);
    setPermission(subFolder, SecurityConstants.ADMINISTRATOR, SecurityConstants.EVERYTHING, true);
    setPermission(subFolder, SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, false);
    assertFalse(fileSystemItemManagerService.canMove(srcFsItemId, destFsItemId, joePrincipal));

    // OK: REMOVE permission on the source backing doc + REMOVE_CHILDREN
    // permission on its parent + ADD_CHILDREN permission on the destination
    // backing doc
    resetPermissions(subFolder, SecurityConstants.EVERYONE);
    resetPermissions(subFolder, "joe");
    setPermission(subFolder, "joe", SecurityConstants.WRITE, true);
    assertTrue(fileSystemItemManagerService.canMove(srcFsItemId, destFsItemId, joePrincipal));

    // Reset permissions
    resetPermissions(rootDoc, "joe");
    resetPermissions(folder, "joe");
    resetPermissions(subFolder, "joe");
  }