@Test
 public void testGetParentPath() throws Exception {
   assertEquals("/", PathHelper.getParentPath("/toto"));
   assertEquals("/toto", PathHelper.getParentPath("/toto/titi"));
   assertEquals("/toto", PathHelper.getParentPath("/toto/titi.tata"));
   assertEquals("/toto.titi", PathHelper.getParentPath("/toto.titi/tata"));
 }
 @Test
 public void testPathDepth() {
   try {
     assertEquals(1, PathHelper.getDepth("/toto"));
     assertEquals(7, PathHelper.getDepth("/1/2/3/4/5/6/7"));
   } catch (Exception e) {
     fail(e.getMessage());
   }
 }
 @Test
 public void splitPathTest() {
   try {
     String[] split1 = {"toto", "titi"};
     String[] split2 = {"toto", "titi", "tata.4", "tete~9", "tutu_8", "tyty-ty", "tagada"};
     assertArrayEquals(split1, PathHelper.splitPath("/toto/titi"));
     assertArrayEquals(
         split2, PathHelper.splitPath("/toto/titi/tata.4/tete~9/tutu_8/tyty-ty/tagada"));
   } catch (Exception e) {
     fail(e.getMessage());
   }
 }
 @Test
 public void testNormalizePath() {
   for (String path : normalizePaths) {
     try {
       PathHelper.valid(path);
       fail("path [" + path + "] should NOT be valid BEFORE normalization");
     } catch (InvalidPathException ive) {
       //
     }
     try {
       PathHelper.valid(PathHelper.normalize(path));
     } catch (InvalidPathException ive) {
       fail("path [" + path + "] should be valid AFTER normalization");
     }
   }
   try {
     assertEquals("/test", PathHelper.normalize("/././././test/./"));
     assertEquals("/", PathHelper.normalize("/test/../../../bidi/../../.."));
     assertEquals("/bidi", PathHelper.normalize("/test/../../../bidi"));
     assertEquals("/bidi/budu", PathHelper.normalize("/test/../bidi/bada/../budu"));
     assertEquals("/bidi/budu", PathHelper.normalize("/test/../bidi/bada/byby/.././../budu"));
   } catch (Exception e) {
     fail(e.getMessage());
   }
 }
 @Test
 public void testValidPath() throws Exception {
   for (String path : validPaths) {
     try {
       PathHelper.valid(path);
     } catch (InvalidPathException ive) {
       fail("path [" + path + "] should be valid");
     }
   }
 }
  /**
   * @param name the name of the project
   * @param summary the description of the project
   * @param path the target location of the new resource
   * @param licence
   */
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void createProject(String path, String name, String summary, String licence)
      throws ProjectException {
    logger.debug("starting project creation");
    try {

      if (name == null || name == "")
        throw new ProjectException("your must specify a name for your project");
      if (summary.length() < 10)
        throw new ProjectException("describe in a more comprehensive manner your project");
      if (summary.length() > 255)
        throw new ProjectException(
            "Your project description is too long. Please make it smaller than 256 bytes.");

      String caller = membership.getProfilePathForConnectedIdentifier();
      // create entity object
      Project project = new Project();
      project.setName(name);
      project.setSummary(summary);
      project.setLicence(licence);
      project.setId(UUID.randomUUID().toString());
      em.persist(project);
      // service orchestration
      pep.checkSecurity(caller, PathHelper.getParentPath(path), "create");

      binding.bind(project.getFactoryResourceIdentifier(), path);
      binding.setProperty(
          path, FactoryResourceProperty.CREATION_TIMESTAMP, System.currentTimeMillis() + "");
      binding.setProperty(
          path, FactoryResourceProperty.LAST_UPDATE_TIMESTAMP, System.currentTimeMillis() + "");
      binding.setProperty(path, FactoryResourceProperty.AUTHOR, caller);

      // create default policy
      String policyId = UUID.randomUUID().toString();
      pap.createPolicy(policyId, PAPServiceHelper.buildOwnerPolicy(policyId, caller, path));
      binding.setProperty(path, FactoryResourceProperty.OWNER, caller);
      binding.setProperty(path, FactoryResourceProperty.POLICY_ID, policyId);

      notification.throwEvent(
          new Event(
              path,
              caller,
              ProjectService.SERVICE_NAME,
              Event.buildEventType(ProjectService.SERVICE_NAME, Project.RESOURCE_NAME, "create"),
              ""));

    } catch (Exception e) {

      ctx.setRollbackOnly();
      throw new ProjectException(e);
    }
  }
  @Override
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void createName(String path, String value) throws GreetingServiceException {

    logger.info("createName(...) called");
    logger.debug("params : path=" + path + ", value=" + value);

    try {
      // Checking if the connected user has the permission to create a resource giving pep :
      //  - the profile path of the connected user (caller)
      //  - the parent of the path (we check the 'create' permission on the parent of the given
      // path)
      //  - the name of the permission to check ('create')
      String caller = membership.getProfilePathForConnectedIdentifier();
      pep.checkSecurity(caller, PathHelper.getParentPath(path), "create");

      // STARTING SPECIFIC EXTERNAL SERVICE RESOURCE CREATION OR METHOD CALL
      Name name = new Name();
      name.setId(UUID.randomUUID().toString());
      name.setValue(value);
      em.persist(name);
      // END OF EXTERNAL INVOCATION

      // Binding the external resource in the naming using the generated resource ID :
      binding.bind(name.getFactoryResourceIdentifier(), path);

      // Need to set some properties on the node :
      binding.setProperty(
          path, FactoryResourceProperty.CREATION_TIMESTAMP, "" + System.currentTimeMillis());
      binding.setProperty(
          path, FactoryResourceProperty.LAST_UPDATE_TIMESTAMP, "" + System.currentTimeMillis());
      binding.setProperty(path, FactoryResourceProperty.AUTHOR, caller);

      // Need to create a new security policy for this resource :
      // Giving the caller the Owner permission (aka all permissions)
      String policyId = UUID.randomUUID().toString();
      pap.createPolicy(policyId, PAPServiceHelper.buildOwnerPolicy(policyId, caller, path));
      pap.createPolicy(
          UUID.randomUUID().toString(),
          PAPServiceHelper.buildPolicy(policyId, caller, path, new String[] {"read"}));

      // Setting security properties on the node :
      binding.setProperty(path, FactoryResourceProperty.OWNER, caller);
      binding.setProperty(path, FactoryResourceProperty.POLICY_ID, policyId);

      // Using the notification service to throw an event :
      notification.throwEvent(
          new Event(
              path,
              caller,
              Name.RESOURCE_NAME,
              Event.buildEventType(GreetingService.SERVICE_NAME, Name.RESOURCE_NAME, "create"),
              ""));

      // Using the indexing service to index the name newly created
      indexing.index(getServiceName(), path);
    } catch (Exception e) {
      ctx.setRollbackOnly();
      logger.error("unable to create the name at path " + path, e);
      throw new GreetingServiceException("unable to create the name at path " + path, e);
    }
  }
  @Override
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public String createForum(String parentPath, String name) throws ForumServiceException {
    String newForumId = null;
    logIt("Create forum under" + parentPath);
    try {
      // Check name
      if (name == null || name == "") {
        throw new ForumServiceException("Forum name is mandatory.");
      }
      // Security check
      String caller = membership.getProfilePathForConnectedIdentifier();
      if (caller == null) {
        throw new ForumServiceException("Could not get connected profile");
      }
      logIt("caller: " + caller);
      // FIXME
      // String path = forumsPath + "/" +
      // CollaborationUtils.normalizeForPath(name);
      // logIt("path:" + path);
      pep.checkSecurity(caller, parentPath, "create");

      // Call WS to create forum
      HashMap<String, String> values = forumWS.createForum(name);
      if (values != null && !values.isEmpty()) {
        String code = (String) values.get("statusCode");
        String msg = (String) values.get("statusMessage");
        String forumId = (String) values.get("forumId");
        logIt("Message Code:" + code + " Message: " + msg);
        if (!code.equals(CollaborationUtils.SUCCESS_CODE)
            || (forumId == null || forumId.equals(""))) {
          throw new ForumServiceException(
              "Error code recieved from the WS." + " Code" + code + " Message:" + msg);
        }
        // Create path based on id that is returned by the Mermig WS
        String path = PathHelper.normalize(parentPath + "/" + forumId);
        logIt("path:" + path);
        // Save the new entity in the factory and bind it
        // We persist only id,path,name
        Forum forum = new Forum();
        forum.setId(forumId);
        forum.setName(name);
        forum.setResourcePath(path);
        // save it
        em.persist(forum);
        // Bind the entity with the path and the identifier
        binding.bind(forum.getFactoryResourceIdentifier(), path);
        binding.setProperty(
            path, FactoryResourceProperty.CREATION_TIMESTAMP, "" + System.currentTimeMillis());
        binding.setProperty(
            path, FactoryResourceProperty.LAST_UPDATE_TIMESTAMP, "" + System.currentTimeMillis());
        binding.setProperty(path, FactoryResourceProperty.AUTHOR, caller);
        // Create policy (owner)
        String policyId = UUID.randomUUID().toString();
        pap.createPolicy(policyId, PAPServiceHelper.buildOwnerPolicy(policyId, caller, path));
        binding.setProperty(path, FactoryResourceProperty.OWNER, caller);
        binding.setProperty(path, FactoryResourceProperty.POLICY_ID, policyId);
        // notify
        notification.throwEvent(
            new Event(
                path,
                caller,
                Forum.RESOURCE_NAME,
                Event.buildEventType(ForumService.SERVICE_NAME, Forum.RESOURCE_NAME, "create"),
                ""));
        newForumId = forumId;
      } else {
        throw new ForumServiceException("No valid answer from the WS.Check logs.");
      }
      return newForumId;
    } catch (Exception e) {
      // ctx.setRollbackOnly();
      logger.error("Unable to create the forum at path " + parentPath, e);
      throw new ForumServiceException("Unable to create the forum at path " + parentPath, e);
    }
  }
  @Override
  public String createMessage(String path, ThreadMessage message, String isReply)
      throws ForumServiceException {

    logIt("createThreadMessage(...) called");
    logger.debug("params : path=" + path + " isReply: " + message);
    String newMsgId = null;
    try {
      // check supplied values
      checkThreadValues(
          message.getName(),
          message.getForumId(),
          message.getMessageBody(),
          message.getDatePosted());
      // Security check
      String caller = membership.getProfilePathForConnectedIdentifier();
      if (caller == null) {
        throw new ForumServiceException("Could not get connected profile");
      }
      logIt("caller: " + caller);
      String parentPath = PathHelper.getParentPath(path);
      pep.checkSecurity(caller, parentPath, "create");
      //
      String parentId = "";
      boolean isReplyBoolean = Boolean.valueOf(isReply);
      logIt("Is Reply: " + isReplyBoolean);
      if (isReplyBoolean) {
        try {
          // Check if parent is thread
          ThreadMessage parentMsg = readThreadMessage(parentPath);
          parentId = parentMsg.getId();
          logIt("Succefully read parent thread. Id: " + parentId);
        } catch (Exception e) {
          throw new ForumServiceException(
              "Path is not valid for replying to a thread.Please check " + path);
        }
      }
      // Call Mermig WS
      HashMap<String, String> values =
          forumWS.createThreadMessage(
              message.getForumId(),
              parentId,
              message.getName(),
              message.getMessageBody(),
              isReplyBoolean);
      //
      if (values != null && !values.isEmpty()) {
        String code = (String) values.get("statusCode");
        String msg = (String) values.get("statusMessage");
        logIt("Message Code:" + code + " Message: " + msg);
        if (!code.equals(CollaborationUtils.SUCCESS_CODE)) {
          throw new ForumServiceException(
              "Error code recieved from the WS." + " Code" + code + " Message:" + msg);
        }
        // We persist only id,path,name,parentId,forumId and author
        String newId = (String) values.get("messageId");
        ThreadMessage tm = new ThreadMessage();
        tm.setId(newId);
        tm.setResourcePath(path);
        tm.setName(message.getName());
        tm.setParentId(parentId);
        tm.setForumId(message.getForumId());
        // FIXME we need author not profile path.
        tm.setAuthor(caller);
        em.persist(tm);
        // Bind the entity with the path and the identifier
        logIt("Bind the " + tm.getFactoryResourceIdentifier() + " to " + path);
        binding.bind(tm.getFactoryResourceIdentifier(), path);
        binding.setProperty(
            path, FactoryResourceProperty.CREATION_TIMESTAMP, "" + System.currentTimeMillis());
        binding.setProperty(
            path, FactoryResourceProperty.LAST_UPDATE_TIMESTAMP, "" + System.currentTimeMillis());
        binding.setProperty(path, FactoryResourceProperty.AUTHOR, caller);
        // Create policy (owner)
        String policyId = UUID.randomUUID().toString();
        pap.createPolicy(policyId, PAPServiceHelper.buildOwnerPolicy(policyId, caller, path));
        binding.setProperty(path, FactoryResourceProperty.OWNER, caller);
        binding.setProperty(path, FactoryResourceProperty.POLICY_ID, policyId);
        // notify
        notification.throwEvent(
            new Event(
                path,
                caller,
                ThreadMessage.RESOURCE_NAME,
                Event.buildEventType(
                    ForumService.SERVICE_NAME, ThreadMessage.RESOURCE_NAME, "create"),
                ""));
        //
        newMsgId = tm.getId();
        logIt(tm.toString());
      } else {
        throw new ForumServiceException("No valid answer from the WS.Check logs.");
      }
      return newMsgId;
    } catch (Exception e) {
      // ctx.setRollbackOnly();
      logger.error("Unable to create the thread message at path " + path, e);
      throw new ForumServiceException("Unable to create the thread message at path " + path, e);
    }
  }