/**
   * Actualitza el tamany de la sèrie.
   *
   * @param nodeRef
   * @param parentNodeRef
   */
  private void updateSerie(NodeService nodeService, NodeRef nodeRef, NodeRef serieNodeRef) {
    System.out.println(
        DateFormat.getInstance().format(new Date()) + " START: Recalcular tamany sèrie.");
    int tamany = 0;
    List<ChildAssociationRef> children = nodeService.getChildAssocs(serieNodeRef);

    for (ChildAssociationRef childAssoc : children) {
      NodeRef childNodeRef = childAssoc.getChildRef();

      if (nodeService.hasAspect(childNodeRef, expedientRM)) {
        Serializable tamanySerial = nodeService.getProperty(childNodeRef, tamanyExpedientRM);

        if (tamanySerial != null) {
          tamany = tamany + (Integer.parseInt((String) tamanySerial));
        }

      } else if (nodeService.hasAspect(childNodeRef, agregacioRM)) {
        Serializable tamanySerial = nodeService.getProperty(childNodeRef, tamanyAgregacioRM);

        if (tamanySerial != null) {
          tamany = tamany + (Integer.parseInt((String) tamanySerial));
        }
      }
    }

    nodeService.setProperty(serieNodeRef, tamanySerieRM, String.valueOf(tamany));
    Date now = new Date();
    System.out.println(
        DateFormat.getInstance().format(now) + " Update tamany sèrie: " + serieNodeRef);
    System.out.println(DateFormat.getInstance().format(now) + " END: Recalcular tamany sèrie.");
  }
  /**
   * Tests that read only methods don't create the shared credentials container, but that write ones
   * will do.
   */
  @Test
  public void testSharedCredentialsContainer() throws Exception {
    // Run as a test user
    AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER_ONE);

    // To start with, the container shouldn't be there
    NodeRef container =
        ((RemoteCredentialsServiceImpl) PRIVATE_REMOTE_CREDENTIALS_SERVICE)
            .getSharedContainerNodeRef(false);
    if (container != null) {
      // Tidy up
      AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();

      // Zap the container
      PUBLIC_NODE_SERVICE.deleteNode(container);
    }

    // Run as a test user
    AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER_ONE);

    // Ask for the list of shared remote systems
    REMOTE_CREDENTIALS_SERVICE.listSharedRemoteSystems(new PagingRequest(10));

    // Won't have been created by a read
    container =
        ((RemoteCredentialsServiceImpl) PRIVATE_REMOTE_CREDENTIALS_SERVICE)
            .getSharedContainerNodeRef(false);
    assertEquals(null, container);

    // Try to store some credentials
    PasswordCredentialsInfo credentials = new PasswordCredentialsInfoImpl();
    REMOTE_CREDENTIALS_SERVICE.createSharedCredentials(TEST_REMOTE_SYSTEM_ONE, credentials);

    // It will now exist
    container =
        ((RemoteCredentialsServiceImpl) PRIVATE_REMOTE_CREDENTIALS_SERVICE)
            .getSharedContainerNodeRef(false);
    assertNotNull(container);

    // Should have a marker aspect, and the specified name
    Set<QName> cAspects = PUBLIC_NODE_SERVICE.getAspects(container);
    assertEquals(
        "Aspect missing, found " + cAspects,
        true,
        cAspects.contains(RemoteCredentialsModel.ASPECT_REMOTE_CREDENTIALS_SYSTEM_CONTAINER));
    assertEquals(
        SHARED_SYSTEM_CONTAINER_NAME,
        PUBLIC_NODE_SERVICE.getProperty(container, ContentModel.PROP_NAME));

    // Should have single node in it
    assertEquals(1, PUBLIC_NODE_SERVICE.getChildAssocs(container).size());

    // Tidy up
    AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();

    // Zap the container
    PUBLIC_NODE_SERVICE.deleteNode(container);
  }
 /**
  * Retrieves the forum node the the given discussable
  *
  * @return Returns the <b>fm:forum</b> node or <tt>null</tt>
  */
 private NodeRef getForum(NodeRef discussableNodeRef) {
   List<ChildAssociationRef> destChildren =
       nodeService.getChildAssocs(
           discussableNodeRef, ForumModel.ASSOC_DISCUSSION, RegexQNamePattern.MATCH_ALL);
   // Take the first one
   if (destChildren.size() == 0) {
     return null;
   } else {
     // We just take the first one
     ChildAssociationRef discussionAssoc = destChildren.get(0);
     return discussionAssoc.getChildRef();
   }
 }
  /**
   * Actualitza el tamany de l'expedient.
   *
   * @param nodeRef
   * @param parentNodeRef
   */
  private void updateExpedient(NodeService nodeService, NodeRef docNodeRef, NodeRef expNodeRef) {
    System.out.println(
        DateFormat.getInstance().format(new Date()) + " START: Recalcular tamany expedient.");
    int tamany = 0;
    List<ChildAssociationRef> children = nodeService.getChildAssocs(expNodeRef);

    for (ChildAssociationRef childAssoc : children) {
      NodeRef childNodeRef = childAssoc.getChildRef();
      Serializable tamanySerial = nodeService.getProperty(childNodeRef, tamanyDocumentSimpleRM);

      if (tamanySerial != null && !"".equals(tamanySerial)) {
        tamany = tamany + (Integer.parseInt((String) tamanySerial));
      }
    }

    nodeService.setProperty(expNodeRef, tamanyExpedientRM, String.valueOf(tamany));
    Date now = new Date();
    System.out.println(
        DateFormat.getInstance().format(now) + " Update tamany expedient: " + expNodeRef);
    System.out.println(DateFormat.getInstance().format(now) + " END: Recalcular tamany expedient.");
  }
  /**
   * Actualitza el tamany del fons.
   *
   * @param nodeRef
   * @param parentNodeRef
   */
  private void updateFons(NodeService nodeService, NodeRef serieNodeRef, NodeRef fonsNodeRef) {
    System.out.println(
        DateFormat.getInstance().format(new Date()) + " START: Recalcular tamany fons.");
    int tamany = 0;
    List<ChildAssociationRef> children = nodeService.getChildAssocs(fonsNodeRef);

    for (ChildAssociationRef childAssoc : children) {
      NodeRef childNodeRef = childAssoc.getChildRef();
      Serializable tamanySerial = nodeService.getProperty(childNodeRef, tamanySerieRM);

      if (tamanySerial != null) {
        tamany = tamany + (Integer.parseInt((String) tamanySerial));
      }
    }

    nodeService.setProperty(fonsNodeRef, tamanyFonsRM, String.valueOf(tamany));
    Date now = new Date();
    System.out.println(
        DateFormat.getInstance().format(now) + " Update tamany fons: " + fonsNodeRef);
    System.out.println(DateFormat.getInstance().format(now) + " END: Recalcular tamany fons.");
  }
  @After
  public void deleteTestNodes() throws Exception {
    AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER);

    // Find the shared system container, and zap contents
    NodeRef container =
        ((RemoteCredentialsServiceImpl) PRIVATE_REMOTE_CREDENTIALS_SERVICE)
            .getSharedContainerNodeRef(false);
    if (container != null) {
      List<NodeRef> children = new ArrayList<NodeRef>();
      for (ChildAssociationRef child : PUBLIC_NODE_SERVICE.getChildAssocs(container)) {
        children.add(child.getChildRef());
      }
      performDeletionOfNodes(children);
    }

    // Zap the users, including any credentials stored for them
    deleteUser(TEST_USER_ONE);
    deleteUser(TEST_USER_TWO);
    deleteUser(TEST_USER_THREE);
  }
  // TODO refactor (see also MessageServiceImpl)
  protected NodeRef resolveQNamePath(NodeRef rootNodeRef, String[] pathPrefixQNameStrings) {
    if (pathPrefixQNameStrings.length == 0) {
      throw new IllegalArgumentException("Path array is empty");
    }
    // walk the path
    NodeRef parentNodeRef = rootNodeRef;
    for (int i = 0; i < pathPrefixQNameStrings.length; i++) {
      String pathPrefixQNameString = pathPrefixQNameStrings[i];

      QName pathQName = null;
      if (tenantAdminService.isEnabled()) {
        String[] parts = QName.splitPrefixedQName(pathPrefixQNameString);
        if ((parts.length == 2) && (parts[0].equals(NamespaceService.APP_MODEL_PREFIX))) {
          String pathUriQNameString =
              new StringBuilder(64)
                  .append(QName.NAMESPACE_BEGIN)
                  .append(NamespaceService.APP_MODEL_1_0_URI)
                  .append(QName.NAMESPACE_END)
                  .append(parts[1])
                  .toString();

          pathQName = QName.createQName(pathUriQNameString);
        } else {
          pathQName = QName.createQName(pathPrefixQNameString, namespaceService);
        }
      } else {
        pathQName = QName.createQName(pathPrefixQNameString, namespaceService);
      }

      List<ChildAssociationRef> childAssocRefs =
          nodeService.getChildAssocs(parentNodeRef, RegexQNamePattern.MATCH_ALL, pathQName);
      if (childAssocRefs.size() != 1) {
        return null;
      }
      parentNodeRef = childAssocRefs.get(0).getChildRef();
    }
    return parentNodeRef;
  }
  /**
   * This method sets the node(s) to publish or unpublish on the supplied publishing details. If the
   * actionedUponNode is a folder then it will include all content nodes within that folder.
   *
   * @param actionedUponNodeRef
   * @param unpublish
   * @param details
   */
  private List<NodeRef> setNodes(
      NodeRef actionedUponNodeRef, boolean unpublish, PublishingDetails details) {
    List<NodeRef> nodes = new ArrayList<NodeRef>();
    QName nodeType = nodeService.getType(actionedUponNodeRef);
    if (dictionaryService.isSubClass(nodeType, ContentModel.TYPE_FOLDER)) {
      List<ChildAssociationRef> children = nodeService.getChildAssocs(actionedUponNodeRef);
      for (ChildAssociationRef childRef : children) {
        NodeRef child = childRef.getChildRef();
        if (dictionaryService.isSubClass(nodeService.getType(child), ContentModel.TYPE_CONTENT)) {
          nodes.add(child);
        }
      }
    } else {
      nodes.add(actionedUponNodeRef);
    }

    if (unpublish) {
      details.addNodesToUnpublish(nodes);
    } else {
      details.addNodesToPublish(nodes);
    }
    return nodes;
  }
  protected List<NodeRef> getNodes(
      StoreRef storeRef, RepositoryLocation repositoryLocation, QName nodeType) {
    List<NodeRef> nodeRefs = new ArrayList<NodeRef>();

    NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
    if (nodeService.exists(rootNodeRef) == false) {
      // Tenant is deleted. But cache refresh was called to inform another cluster nodes
      // Should be reworked when MNT-11638 will be implemented
      return nodeRefs;
    }

    if (repositoryLocation instanceof DynamicCreateRepositoryLocation) {
      ((DynamicCreateRepositoryLocation) repositoryLocation).checkAndCreate(rootNodeRef);
    }

    String[] pathElements = repositoryLocation.getPathElements();

    NodeRef folderNodeRef = rootNodeRef;
    if (pathElements.length > 0) {
      folderNodeRef = resolveQNamePath(rootNodeRef, pathElements);
    }

    if (folderNodeRef != null) {
      Set<QName> types = new HashSet<QName>(1);
      types.add(nodeType);
      List<ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(folderNodeRef, types);

      if (childAssocRefs.size() > 0) {
        nodeRefs = new ArrayList<NodeRef>(childAssocRefs.size());
        for (ChildAssociationRef childAssocRef : childAssocRefs) {
          nodeRefs.add(childAssocRef.getChildRef());
        }
      }
    }

    return nodeRefs;
  }
  public void onCopyComplete(
      QName classRef,
      NodeRef sourceNodeRef,
      NodeRef targetNodeRef,
      boolean copyToNewNode,
      Map<NodeRef, NodeRef> copyMap) {
    Set<NodeRef> workingCopyNodeRefs = TransactionalResourceHelper.getSet(KEY_WORKING_COPIES);
    if (!workingCopyNodeRefs.contains(sourceNodeRef)) {
      // This is not one of the nodes that needs to have discussions copied over
      return;
    }

    // First check that the source node has forums
    NodeRef sourceForumNodeRef = getForum(sourceNodeRef);
    if (sourceForumNodeRef == null) {
      // Missing!  Clean the source node up!
      nodeService.removeAspect(sourceNodeRef, ForumModel.ASPECT_DISCUSSABLE);
      return;
    }

    // The aspect may or may not exist on the target node
    if (!nodeService.hasAspect(targetNodeRef, ForumModel.ASPECT_DISCUSSABLE)) {
      // Add the aspect
      nodeService.addAspect(targetNodeRef, ForumModel.ASPECT_DISCUSSABLE, null);
    }
    // Get the forum node
    NodeRef targetForumNodeRef = getForum(targetNodeRef);
    // Merge the forum topics
    List<ChildAssociationRef> topicAssocRefs =
        nodeService.getChildAssocs(
            sourceForumNodeRef, Collections.singleton(ForumModel.TYPE_TOPIC));
    int copied = 0;
    for (ChildAssociationRef topicAssocRef : topicAssocRefs) {
      NodeRef topicNodeRef = topicAssocRef.getChildRef();
      try {
        // work out the name for the copied topic
        String topicName;
        String topicNodeName =
            nodeService.getProperty(topicNodeRef, ContentModel.PROP_NAME).toString();
        Serializable labelProp =
            nodeService.getProperty(targetNodeRef, ContentModel.PROP_VERSION_LABEL);
        if (labelProp == null) {
          SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
          topicName = topicNodeName + " - " + dateFormat.format(new Date());
        } else {
          topicName = topicNodeName + " (" + labelProp.toString() + ")";
        }

        if (fileFolderService.searchSimple(targetForumNodeRef, topicName) != null) {
          // A topic with that name already exists
          continue;
        }
        fileFolderService.copy(topicNodeRef, targetForumNodeRef, topicName);
        copied++;
      } catch (FileExistsException e) {
        // We checked for this, so this is a concurrency condition
        throw new ConcurrencyFailureException("Target topic exists: " + e.getMessage(), e);
      } catch (FileNotFoundException e) {
        // The node was there, but now it's gone
        throw new ConcurrencyFailureException("Forum was deleted: " + e.getMessage(), e);
      }
    }
  }
  @Override
  protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {

    long startTime = System.currentTimeMillis();

    logger.info("DEBUT Web Script SynchroniseDroitsSHDWebScript");

    Map<String, Object> model = new HashMap<String, Object>();
    model.put("nomWebScript", "SynchroniseDroitsSHDWebScript");

    if (!isSiteSirhExist()) {
      logger.debug("Site SIRH not exist");

      long endTime = System.currentTimeMillis();

      model.put("nbrAgentCree", "Site SIRH not exist");
      model.put("tempsExecution", endTime - startTime);

      return model;
    }

    NodeRef nodeAgents =
        alfrescoUtilsService.getNodeRef(
            "/app:company_home/site:sites/cm:SIRH/cm:documentLibrary/cm:Agents");

    List<ChildAssociationRef> listChildren = nodeService.getChildAssocs(nodeAgents);

    int nbrAgentCree = 0;
    if (null != listChildren && 0 < listChildren.size()) {
      for (ChildAssociationRef child : listChildren) {
        // nous gerons nous meme les transactions
        // car nous avons eu "TransactionalCache' is full"
        // cela ralentit fortement Alfresco
        UserTransaction trx =
            serviceRegistry.getTransactionService().getNonPropagatingUserTransaction(false);
        try {
          trx.begin();

          String nameFolderAgent =
              (String) nodeService.getProperty(child.getChildRef(), ContentModel.PROP_NAME);
          Integer idAgent = null;
          try {
            idAgent =
                new Integer(
                    nameFolderAgent.substring(
                        nameFolderAgent.length() - 7, nameFolderAgent.length()));
          } catch (NumberFormatException e) {
            logger.error("Error ParseException Node : " + nameFolderAgent);
            idAgent = null;
          }

          if (null != idAgent) {
            logger.debug("Add SHD Rights to " + idAgent);
            traiteDroitsOfNodeAgent(child, idAgent, nameFolderAgent);
            nbrAgentCree++;
          }

          trx.commit();
        } catch (Throwable e) {
          try {
            trx.rollback();
          } catch (IllegalStateException | SecurityException | SystemException e1) {
            logger.error(e1.getMessage());
          }
        }
      }
    }

    long endTime = System.currentTimeMillis();

    logger.info("FIN Web Script SynchroniseDroitsSHDWebScript");

    model.put("tempsExecution", endTime - startTime);
    model.put("nombreAgentsAjoutesSHD", nbrAgentCree);

    return model;
  }