/* * Copyright (C) 2005-2012 BetaCONCEPT Limited * * This file is part of Astroboa. * * Astroboa is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Astroboa is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Astroboa. If not, see <http://www.gnu.org/licenses/>. */ package org.betaconceptframework.astroboa.engine.jcr.dao; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jcr.ItemNotFoundException; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.ValueFormatException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.CmsApiConstants; import org.betaconceptframework.astroboa.api.model.CmsRepositoryEntity; import org.betaconceptframework.astroboa.api.model.RepositoryUser; import org.betaconceptframework.astroboa.api.model.RepositoryUserType; import org.betaconceptframework.astroboa.api.model.Space; import org.betaconceptframework.astroboa.api.model.Taxonomy; import org.betaconceptframework.astroboa.api.model.definition.Localization; import org.betaconceptframework.astroboa.api.model.exception.CmsException; import org.betaconceptframework.astroboa.api.model.io.ImportConfiguration; import org.betaconceptframework.astroboa.api.model.io.ImportConfiguration.PersistMode; import org.betaconceptframework.astroboa.api.model.query.criteria.ContentObjectCriteria; import org.betaconceptframework.astroboa.api.model.query.criteria.RepositoryUserCriteria; import org.betaconceptframework.astroboa.api.model.query.criteria.SpaceCriteria; import org.betaconceptframework.astroboa.api.model.query.render.RenderProperties; import org.betaconceptframework.astroboa.engine.cache.regions.JcrQueryCacheRegion; import org.betaconceptframework.astroboa.engine.database.dao.CmsRepositoryEntityAssociationDao; import org.betaconceptframework.astroboa.engine.jcr.query.CmsQueryHandler; import org.betaconceptframework.astroboa.engine.jcr.query.CmsQueryResult; import org.betaconceptframework.astroboa.engine.jcr.renderer.RepositoryUserRenderer; import org.betaconceptframework.astroboa.engine.jcr.util.CmsLocalizationUtils; import org.betaconceptframework.astroboa.engine.jcr.util.CmsRepositoryEntityUtils; import org.betaconceptframework.astroboa.engine.jcr.util.Context; import org.betaconceptframework.astroboa.engine.jcr.util.EntityAssociationDeleteHelper; import org.betaconceptframework.astroboa.engine.jcr.util.EntityAssociationUpdateHelper; import org.betaconceptframework.astroboa.engine.jcr.util.JcrNodeUtils; import org.betaconceptframework.astroboa.engine.jcr.util.RendererUtils; import org.betaconceptframework.astroboa.engine.jcr.util.SpaceUtils; import org.betaconceptframework.astroboa.model.factory.CmsCriteriaFactory; import org.betaconceptframework.astroboa.model.factory.CmsRepositoryEntityFactoryForActiveClient; import org.betaconceptframework.astroboa.model.impl.RepositoryUserImpl; import org.betaconceptframework.astroboa.model.impl.item.CmsBuiltInItem; import org.betaconceptframework.astroboa.util.CmsConstants; import org.springframework.beans.factory.annotation.Autowired; /** * * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ public class RepositoryUserDao extends JcrDaoSupport { @Autowired private CmsRepositoryEntityUtils cmsRepositoryEntityUtils; @Autowired private JcrQueryCacheRegion jcrQueryCacheRegion; @Autowired private RendererUtils rendererUtils; @Autowired private CmsQueryHandler cmsQueryHandler; @Autowired private RepositoryUserRenderer repositoryUserRenderer; @Autowired private CmsLocalizationUtils cmsLocalizationUtils; @Autowired private ContentObjectDao contentObjectDao; @Autowired private SpaceUtils spaceUtils; /** * Provides localized labels for folksonomies */ private Localization defaultFolksonomyLocalization; /** * Provides localized labels for Spaces */ private Localization defaultSpaceLocalization; @Autowired private CmsRepositoryEntityAssociationDao cmsRepositoryEntityAssociationDao; @Autowired private ImportDao importDao; public void setDefaultSpaceLocalization(Localization defaultSpaceLocalization) { this.defaultSpaceLocalization = defaultSpaceLocalization; } public void setDefaultFolksonomyLocalization( Localization defaultFolksonomyLocalization) { this.defaultFolksonomyLocalization = defaultFolksonomyLocalization; } public RepositoryUser getSystemRepositoryUser() { return getRepositoryUser(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID); } public void removeRepositoryUserAndOwnedObjects(String repositoryUserId) { removeRepositoryUser(repositoryUserId, null, true); } private void removeRepositoryUser(String repositoryUserId, RepositoryUser alternativeUser, boolean removeObjectsWhoseOwnerIsTheUserToBeDeleted) { Context context = null; try{ Session session = getSession(); if (StringUtils.isBlank(repositoryUserId)) throw new ItemNotFoundException("Undefined repository user id "+ repositoryUserId); // Retrieve user node to be removed Node repositoryUserNode = cmsRepositoryEntityUtils.retrieveUniqueNodeForRepositoryUser(session, repositoryUserId); if (repositoryUserNode == null) throw new CmsException("No repository User found with Id "+ repositoryUserId); if (repositoryUserNode.hasProperty(CmsBuiltInItem.ExternalId.getJcrName())){ String externalId = repositoryUserNode.getProperty(CmsBuiltInItem.ExternalId.getJcrName()).getString(); if (CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID.equals(externalId)){ throw new CmsException("Invalid delete operation. SYSTEM RepositoryUser cannot be deleted."); } } if (alternativeUser == null && ! removeObjectsWhoseOwnerIsTheUserToBeDeleted){ throw new CmsException("No alternative user has been provided"); } context = new Context(cmsRepositoryEntityUtils, cmsQueryHandler, session); //Save any alternative user if (alternativeUser != null){ updateRepositoryUserNode(session, alternativeUser, context); } //remove all node References removeReferencesForRepositoryUser(session,alternativeUser, removeObjectsWhoseOwnerIsTheUserToBeDeleted, repositoryUserId, context); //remove user node repositoryUserNode.remove(); session.save(); //Notify cache //jcrQueryCacheRegion.removeRegion(); } catch (Exception e) { throw new CmsException(e); } finally{ if (context != null){ context.dispose(); context = null; } } } public void removeRepositoryUser(String repositoryUserId, RepositoryUser alternativeUser) { removeRepositoryUser(repositoryUserId, alternativeUser, (alternativeUser == null)); } public RepositoryUser saveRepositoryUser(Object repositoryUserSource) { if (repositoryUserSource == null){ throw new CmsException("Cannot save an empty RepositoryUser !"); } if (repositoryUserSource instanceof String){ //Use importer to unmarshal String to RepositoryUser //and to save it as well. //What is happened is that importDao will create a RepositoryUser //and will pass it here again to save it. ImportConfiguration configuration = ImportConfiguration.repositoryUser() .persist(PersistMode.PERSIST_MAIN_ENTITY) .build(); return importDao.importRepositoryUser((String)repositoryUserSource, configuration); } if (! (repositoryUserSource instanceof RepositoryUser)){ throw new CmsException("Expecting either String or RepositoryUser and not "+repositoryUserSource.getClass().getName()); } RepositoryUser repositoryUser = (RepositoryUser) repositoryUserSource; Context context = null; try { Session session = getSession(); context = new Context(cmsRepositoryEntityUtils, cmsQueryHandler, session); updateRepositoryUserNode(session,repositoryUser, context); session.save(); //Inform cache //jcrQueryCacheRegion.removeRegion(); return repositoryUser; } catch (Exception e) { throw new CmsException(e); } finally{ if (context != null){ context.dispose(); context = null; } } } public List<RepositoryUser> searchRepositoryUsers(RepositoryUserCriteria repositoryUserCriteria) { Session session = null; if (repositoryUserCriteria== null) throw new CmsException("Null repository user criteria"); try { //For some reason user has asked for 0 limit //Returned an empty list. No need to perform the //query. this method output must be changed to CmsOutcome //in order to provide user with the total result count //even when limit is 0 , that is no result should be returned if (repositoryUserCriteria.getLimit() == 0){ return new ArrayList<RepositoryUser>(); } List<RepositoryUser> repositoryUserList = null; if (repositoryUserCriteria.isCacheable()){ //Search in cache repositoryUserList = (List<RepositoryUser>) jcrQueryCacheRegion.getJcrQueryResults(repositoryUserCriteria); } if (repositoryUserList != null) return repositoryUserList; else{ session = getSession(); repositoryUserList = new ArrayList<RepositoryUser>(); //Need new instance in case during rendering render instructions are updated RenderProperties renderPropertiesForCache = rendererUtils.copyRenderPropertiesFromCriteria(repositoryUserCriteria); //CmsQueryResultSecurityHandler cmsQueryResultSecurityHandler = new CmsQueryResultSecurityHandler(cmsQueryHandler, // repositoryUserCriteria,session, accessManager); CmsQueryResult cmsQueryResult = cmsQueryHandler.getNodesFromXPathQuery(session, repositoryUserCriteria); NodeIterator nodeIterator = cmsQueryResult.getNodeIterator(); Map<String, CmsRepositoryEntity> cachedRepositoryEntities = new HashMap<String, CmsRepositoryEntity>(); List<String> repositoryUserIdsForCache = new ArrayList<String>(); while (nodeIterator.hasNext()){ RepositoryUser repositoryUser = renderRepositoryUserFromNode(nodeIterator.nextNode(), session, repositoryUserCriteria.getRenderProperties(), cachedRepositoryEntities); repositoryUserList.add(repositoryUser); repositoryUserIdsForCache.add(repositoryUser.getId()); } //Cache results if (repositoryUserCriteria.isCacheable()){ if (!StringUtils.isBlank(repositoryUserCriteria.getXPathQuery()) && CollectionUtils.isNotEmpty(repositoryUserList)){ jcrQueryCacheRegion.cacheJcrQueryResults(repositoryUserCriteria, repositoryUserList, renderPropertiesForCache); } } return repositoryUserList; } } catch (Exception e) { throw new CmsException(e); } } public RepositoryUser renderRepositoryUserFromNode( Node node, Session session, RenderProperties renderProperties, Map<String, CmsRepositoryEntity> cachedRepositoryEntities) throws RepositoryException { return repositoryUserRenderer.renderRepositoryUserNode(node, renderProperties, session, cachedRepositoryEntities); } private void updateRepositoryUserNode(Session session, RepositoryUser repositoryUser, Context context) throws RepositoryException{ Node repositoryUserNode = retrieveOrCreateRepositoryUserNode(session, repositoryUser); populateRepositoryUserNode(repositoryUserNode, repositoryUser, session, context); } private Node retrieveOrCreateRepositoryUserNode(Session session, RepositoryUser repositoryUser) throws RepositoryException{ //1. ExternalId is not provided. Search user using its identifier if (StringUtils.isBlank(repositoryUser.getExternalId())){ if (repositoryUser.getId() == null){ throw new CmsException("Repository user has not external id and no cms identifier"); } else{ //Search for a repository user node with provided identifier Node repositoryUserNode = cmsRepositoryEntityUtils.retrieveUniqueNodeForRepositoryUser(session, repositoryUser.getId()); if (repositoryUserNode != null) { return repositoryUserNode; } else { throw new CmsException("Could not update repository user "+repositoryUser.toString()+ " because no repository user with such id is found in repository and externalId is not provided"); } } } else{ //2.External Id is provided. //a. Check external Id belongs to SYSTEM user if (CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID.equals(repositoryUser.getExternalId())){ //SYSTEM user is updated. Retrieve system repository user node //In case repositoryUser instance has an identifier ignore it return retrieveSystemRepositoryUserNode(session, true); } else{ //Check how many users exist with the same external id Node existingRepositoryUserNode = checkForDuplicateExternalId(repositoryUser, session); if (existingRepositoryUserNode != null){ return existingRepositoryUserNode; } else{ //No node found with provided identifier and/or external Id. Create new node return createRepositoryUserNode(repositoryUser, session); } } } } public RepositoryUser createSystemRepositoryUser(){ Context context = null; try { Session session = getSession(); if (retrieveSystemRepositoryUserNode(session, false) != null){ throw new Exception("RepositoryUser SYSTEM already exists"); } RepositoryUser systemUser = CmsRepositoryEntityFactoryForActiveClient.INSTANCE.getFactory().newRepositoryUser(); systemUser.setExternalId(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID); systemUser.setLabel(CmsApiConstants.SYSTEM_REPOSITORY_USER_LABEL); Node systemUserNode = createRepositoryUserNode(systemUser, session); context = new Context(cmsRepositoryEntityUtils, cmsQueryHandler, session); populateRepositoryUserNode(systemUserNode, systemUser, session, context); session.save(); return systemUser; } catch (Exception e) { throw new CmsException(e); } finally{ if (context != null){ context.dispose(); context = null; } } } private Node retrieveSystemRepositoryUserNode(Session session, boolean throwExceptionIfNotFound) throws RepositoryException { RepositoryUserCriteria userCriteria = CmsCriteriaFactory.newRepositoryUserCriteria(); userCriteria.doNotCacheResults(); userCriteria.setLimit(1); userCriteria.addExternalIdEqualsCriterion(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID); CmsQueryResult systemUserQueryResult = cmsQueryHandler.getNodesFromXPathQuery(session, userCriteria); if (systemUserQueryResult == null || systemUserQueryResult.getTotalRowCount() == 0) { if (throwExceptionIfNotFound) { throw new RepositoryException("Problem with locating system repository user node. Query "+ userCriteria.getXPathQuery() + " did not returned 1 node"); } else { return null; } } else if (systemUserQueryResult.getTotalRowCount() == 1) { return systemUserQueryResult.getNodeIterator().nextNode(); } else { throw new RepositoryException("Problem with locating system repository user node. Found more than one jcr nodes representing system repository user"); } } private Node createRepositoryUserNode(RepositoryUser repositoryUser, Session session) throws RepositoryException { Node repositoryUserNode = JcrNodeUtils.addRepositoryUserNode(session); //Create CmsIdentifier cmsRepositoryEntityUtils.createCmsIdentifier(repositoryUserNode, repositoryUser, true); return repositoryUserNode; } private void populateRepositoryUserNode(Node repositoryUserNode, RepositoryUser repositoryUser, Session session, Context context) throws RepositoryException { String repositoryUserExternalId = repositoryUser.getExternalId(); //External Id. Update it only if it does not exists if (! repositoryUserNode.hasProperty(CmsBuiltInItem.ExternalId.getJcrName())) { repositoryUserNode.setProperty(CmsBuiltInItem.ExternalId.getJcrName(), repositoryUserExternalId); } //or it is not SYSTEM RepositoyUser ExternalId and it is not the same with the one existed else{ String existingExternalId = repositoryUserNode.getProperty(CmsBuiltInItem.ExternalId.getJcrName()).getString(); boolean repositoryUserExternalIdIsDifferentThanExisting = ! existingExternalId.equals(repositoryUserExternalId); if (repositoryUserExternalIdIsDifferentThanExisting) { if (CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID.equals(existingExternalId)) { throw new RepositoryException("Invalid operation. Tried to update SYSTEM repository user externalId."); } else { repositoryUserNode.setProperty(CmsBuiltInItem.ExternalId.getJcrName(), repositoryUserExternalId); } } } //Label repositoryUserNode.setProperty(CmsBuiltInItem.Label.getJcrName(), repositoryUser.getLabel()); //User Type if (repositoryUser.getUserType() == null){ repositoryUser.setUserType(RepositoryUserType.User); } repositoryUserNode.setProperty(CmsBuiltInItem.UserType.getJcrName(), repositoryUser.getUserType().toString()); populateSpace(repositoryUser, repositoryUserNode, session, context); populateFolksonomy(repositoryUser, repositoryUserNode, session); // TODO Preferences Implement method populatePreferences(repositoryUser, repositoryUserNode); } private Node checkForDuplicateExternalId(RepositoryUser repositoryUserToBeSaved, Session session) throws RepositoryException, ValueFormatException, PathNotFoundException { RepositoryUserCriteria userCriteria = CmsCriteriaFactory.newRepositoryUserCriteria(); userCriteria.doNotCacheResults(); userCriteria.setLimit(2); userCriteria.addExternalIdEqualsCriterion(repositoryUserToBeSaved.getExternalId()); CmsQueryResult usersWithTheSameExternalId = cmsQueryHandler.getNodesFromXPathQuery(session, userCriteria); if (usersWithTheSameExternalId != null) { if (usersWithTheSameExternalId.getTotalRowCount() > 1) { throw new RepositoryException("Found more than one repository users with the same external id "+ repositoryUserToBeSaved.getExternalId()); } if (usersWithTheSameExternalId.getTotalRowCount() == 1) { if (repositoryUserToBeSaved.getId() == null) { throw new RepositoryException("A repository user with the same external id "+ repositoryUserToBeSaved.getExternalId() + " already exists."); } else{ Node existingRepositoryUserNode = usersWithTheSameExternalId.getNodeIterator().nextNode(); //Must be the same node if (! existingRepositoryUserNode.hasProperty(CmsBuiltInItem.CmsIdentifier.getJcrName()) || ! existingRepositoryUserNode.getProperty(CmsBuiltInItem.CmsIdentifier.getJcrName()).getString().equals(repositoryUserToBeSaved.getId())) { throw new RepositoryException("A repository user with the same external id "+ repositoryUserToBeSaved.getExternalId() + " already exists."); } return existingRepositoryUserNode; } } } //No other node found with the same external id. in case identifier is provided return null; } private void populateFolksonomy(RepositoryUser repositoryUser, Node repositoryUserNode, Session session) throws RepositoryException { Taxonomy repositoryUserFolksonomy = repositoryUser.getFolksonomy(); if (repositoryUserFolksonomy == null){ ((RepositoryUserImpl)repositoryUser).setFolksonomy(cmsRepositoryEntityFactoryForActiveClient.newTaxonomy()); repositoryUserFolksonomy = repositoryUser.getFolksonomy(); } //Folksonomy node should have already been created. No need to check for it existence Node folksonomyNode = repositoryUserNode.getNode(CmsBuiltInItem.Folksonomy.getJcrName()); //If repository user folksonomy has no localized labels use the default if (! repositoryUserFolksonomy.hasLocalizedLabels() && MapUtils.isNotEmpty(defaultFolksonomyLocalization.getLocalizedLabels())){ repositoryUserFolksonomy.getLocalizedLabels().putAll(defaultFolksonomyLocalization.getLocalizedLabels()); } //Update localization for repository user folksonomy cmsLocalizationUtils.updateCmsLocalization(repositoryUserFolksonomy, folksonomyNode); // In case repository user is a new user and its folksonomy does not have a name String providedFolksonomyName = repositoryUserFolksonomy.getName(); if (StringUtils.isBlank(providedFolksonomyName)){ repositoryUserFolksonomy.setName(folksonomyNode.getName()); } else{ //Folksonomy Name is a fixed name and should never change if (!folksonomyNode.getName().equals(providedFolksonomyName)){ throw new RepositoryException("Invalid folksonomy name "+ providedFolksonomyName); } } //Create Folksonomy Identifier if folksonomy is a new one if (folksonomyNode.isNew()){ if (cmsRepositoryEntityUtils.hasCmsIdentifier(folksonomyNode)){ //This should never happen throw new CmsException("Folskonomy jcr node is new but an idnetifier property already exists"); } //Create a Astroboa identifier for folskonomy or use the one provided cmsRepositoryEntityUtils.createCmsIdentifier(folksonomyNode, repositoryUserFolksonomy, true); } else{ //Folksonomy node is not new. Check that an identifier exists if (!cmsRepositoryEntityUtils.hasCmsIdentifier(folksonomyNode)) { cmsRepositoryEntityUtils.createCmsIdentifier(folksonomyNode, repositoryUserFolksonomy, true); } else { String folksonomyIdentifier = cmsRepositoryEntityUtils.getCmsIdentifier(folksonomyNode); //User has provided an identifier for folksonomy. //Check if it matches with the one in folksonomy jcr node if (repositoryUserFolksonomy.getId() != null){ if (!repositoryUserFolksonomy.getId().equals(folksonomyIdentifier) && ! StringUtils.equals(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID, repositoryUser.getExternalId())) { throw new CmsException("Folksonomy identifier "+folksonomyIdentifier + " for repository user "+ repositoryUser.getLabel()+ " does not match with the provided identifier "+repositoryUserFolksonomy.getId()); } } else{ //User does not have an identifier for folksonomy. Update its value repositoryUserFolksonomy.setId(folksonomyIdentifier); } } } } private void populatePreferences(RepositoryUser repositoryUser, Node repositoryUserNode) { } private void populateSpace(RepositoryUser repositoryUser, Node repositoryUserNode, Session session, Context context) throws RepositoryException { Space repositoryUserSpace = repositoryUser.getSpace(); if (repositoryUserSpace == null){ ((RepositoryUserImpl)repositoryUser).setSpace(cmsRepositoryEntityFactoryForActiveClient.newSpace()); repositoryUserSpace = repositoryUser.getSpace(); } if (! repositoryUser.getSpace().hasLocalizedLabels() && MapUtils.isNotEmpty(defaultSpaceLocalization.getLocalizedLabels())){ repositoryUser.getSpace().getLocalizedLabels().putAll(defaultSpaceLocalization.getLocalizedLabels()); } if (repositoryUserSpace.getName() == null){ repositoryUserSpace.setName("spaceForUser"+ repositoryUser.getExternalId()); } //Since Space name must follow a specific pattern, check if repository user space name is valid. //if not then issue a warning and replace value with a default value. if (!cmsRepositoryEntityUtils.isValidSystemName(repositoryUserSpace.getName())){ //First try to remove all white spaces, in case space name has not changed since it was first created by the //following line of code //repositoryUserSpace.setName("Space for user"+ repositoryUser.getExternalId()); String nameWithoutWhiteSpaces = StringUtils.deleteWhitespace(repositoryUserSpace.getName()); if (!cmsRepositoryEntityUtils.isValidSystemName(nameWithoutWhiteSpaces)){ //Name is still invalid. Issue a warning and replace name so that save can continue safely logger.warn("Repository User's '{}' Space name '{}' does not follow pattern {} and to will change to 'spaceForUser'. " + " In order to provide a different name you must explicitly save RepositotyUser Space by using SpaceService.", new Object[]{repositoryUser.getLabel(), repositoryUserSpace.getName(), CmsConstants.SYSTEM_NAME_REG_EXP}); } else{ repositoryUserSpace.setName(nameWithoutWhiteSpaces); } } //Create Space if it does not exist Node spaceNode = null; if (!repositoryUserNode.hasNode(CmsBuiltInItem.Space.getJcrName())){ repositoryUserSpace.setOwner(repositoryUser); repositoryUserSpace.setOrder(Long.valueOf(1)); //Create new node spaceNode = JcrNodeUtils.addSpaceNode(repositoryUserNode, CmsBuiltInItem.Space.getJcrName()); //Create a Astroboa identifier for space or use the one provided cmsRepositoryEntityUtils.createCmsIdentifier(spaceNode, repositoryUserSpace, true); //Set Owner //Inform associations about relation between new space and repository user EntityAssociationUpdateHelper<RepositoryUser> repositoryUserAssociationUpdateHelper = new EntityAssociationUpdateHelper<RepositoryUser>(session,cmsRepositoryEntityAssociationDao, context); repositoryUserAssociationUpdateHelper.setReferrerCmsRepositoryEntityNode(spaceNode); repositoryUserAssociationUpdateHelper.setReferrerPropertyName(CmsBuiltInItem.OwnerCmsIdentifier); repositoryUserAssociationUpdateHelper.setValuesToBeAdded(Arrays.asList(repositoryUser)); repositoryUserAssociationUpdateHelper.update(); } else { spaceNode = repositoryUserNode.getNode(CmsBuiltInItem.Space.getJcrName()); if (! repositoryUser.getSpace().hasLocalizedLabels() && MapUtils.isNotEmpty(defaultSpaceLocalization.getLocalizedLabels())){ repositoryUser.getSpace().getLocalizedLabels().putAll(defaultSpaceLocalization.getLocalizedLabels()); } //Space node is not new. Check that an identifier exists if (!cmsRepositoryEntityUtils.hasCmsIdentifier(spaceNode)) { cmsRepositoryEntityUtils.createCmsIdentifier(spaceNode, repositoryUserSpace, true); } else { String spaceIdentifier = cmsRepositoryEntityUtils.getCmsIdentifier(spaceNode); //User has provided an identifier for space //Check if it matches with the one in space jcr node only if space does not represent SYSTEM's space if (repositoryUserSpace.getId() != null){ if (!repositoryUserSpace.getId().equals(spaceIdentifier) && ! StringUtils.equals(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID, repositoryUser.getExternalId())) { throw new CmsException("Space identifier "+spaceIdentifier + " for repository user "+ repositoryUser.getLabel()+ " does not match with the provided identifier "+repositoryUserSpace.getId()); } } else { //User does not have an identifier for space. Update its value repositoryUserSpace.setId(spaceIdentifier); } } } //Update localization for repository user space spaceUtils.updateLocalizedLabels(repositoryUser.getSpace(), spaceNode); //Populate Node with default values spaceUtils.updateOrder(repositoryUser.getSpace(), spaceNode); spaceUtils.updateName(repositoryUser.getSpace(), spaceNode); } private void removeReferencesForRepositoryUser(Session session, RepositoryUser alternativeUser, boolean removeObjectsWhoseOwnerIsTheUserToBeDeleted, String repositoryUserId, Context context) throws Exception { if (removeObjectsWhoseOwnerIsTheUserToBeDeleted){ removeObjectsWhoseOwnerIsTheUserToBeDeleted(session, repositoryUserId, context); } else{ RepositoryUser userToBeRemoved = cmsRepositoryEntityFactoryForActiveClient.newRepositoryUser(); userToBeRemoved.setId(repositoryUserId); EntityAssociationDeleteHelper<RepositoryUser> repositoryUserRemover = new EntityAssociationDeleteHelper<RepositoryUser>(session,cmsRepositoryEntityAssociationDao, context); if (alternativeUser != null){ repositoryUserRemover.setCmsRepositoryEntityIdReplacement(alternativeUser.getId()); } repositoryUserRemover.setCmsRepositoryEntityIdToBeRemoved(userToBeRemoved.getId()); repositoryUserRemover.removeOrReplaceAllReferences(RepositoryUser.class); } } private void removeObjectsWhoseOwnerIsTheUserToBeDeleted(Session session, String repositoryUserId, Context context) throws RepositoryException { removeContentObjectsOwnedByUser(repositoryUserId, session, context); removeSpacesOwnedByUser(repositoryUserId, session, context); } private void removeContentObjectsOwnedByUser(String repositoryUserId, Session session, Context context) throws RepositoryException { ContentObjectCriteria contentObjectCriteria = CmsCriteriaFactory.newContentObjectCriteria(); contentObjectCriteria.addOwnerIdEqualsCriterion(repositoryUserId); NodeIterator contentObjectNodesFound = cmsQueryHandler.getNodesFromXPathQuery(session, contentObjectCriteria).getNodeIterator(); while (contentObjectNodesFound.hasNext()){ Node contentObjectNode = contentObjectNodesFound.nextNode(); contentObjectDao.removeContentObjectNode(contentObjectNode, true, session, context); } } private void removeSpacesOwnedByUser(String repositoryUserId, Session session, Context context) throws RepositoryException { Map<String, Node> spacesToBeDeleted = new HashMap<String, Node>(); SpaceCriteria spaceCriteria = CmsCriteriaFactory.newSpaceCriteria(); spaceCriteria.addOwnerIdEqualsCriterion(repositoryUserId); NodeIterator spacesFound = cmsQueryHandler.getNodesFromXPathQuery(session, spaceCriteria).getNodeIterator(); while (spacesFound.hasNext()){ Node spaceNode = spacesFound.nextNode(); //Organization Space is not to be deleted if (Space.ORGANIZATION_SPACE_NAME.equalsIgnoreCase(spaceNode.getName())){ throw new CmsException(Space.ORGANIZATION_SPACE_NAME +" cannot be deleted"); } Node parent = spaceNode.getParent(); if (!parent.isNodeType(CmsBuiltInItem.RepositoryUser.getJcrName()) && !spacesToBeDeleted.containsKey(spaceNode.getIdentifier())){ boolean found = false; //Iterate through space tree to see if its parent is marked for deletion while (parent != null && parent.isNodeType(CmsBuiltInItem.Space.getJcrName())){ if (!spacesToBeDeleted.containsKey(parent.getIdentifier())){ parent = parent.getParent(); } else{ found = true; break; } } if (!found){ spacesToBeDeleted.put(spaceNode.getIdentifier(), spaceNode); } } } if (MapUtils.isNotEmpty(spacesToBeDeleted)){ for (Node node : spacesToBeDeleted.values()){ spaceUtils.removeSpaceJcrNode(node, session, true, context); } } } public RepositoryUser getRepositoryUser(String externalId) { if (StringUtils.isBlank(externalId)){ throw new CmsException("No external id provided"); } RepositoryUserCriteria repositoryUserCriteria = CmsCriteriaFactory.newRepositoryUserCriteria(); repositoryUserCriteria.addExternalIdEqualsCriterion(externalId); repositoryUserCriteria.setOffsetAndLimit(0, 1); List<RepositoryUser> repositoryUsers = searchRepositoryUsers(repositoryUserCriteria); if (CollectionUtils.isNotEmpty(repositoryUsers) && repositoryUsers.size() > 1){ throw new CmsException("Found more than one repository user with external id "+ externalId); } return repositoryUsers.isEmpty() ? null : repositoryUsers.get(0); } }