/* * 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.util; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.CmsApiConstants; import org.betaconceptframework.astroboa.api.model.ContentObject; import org.betaconceptframework.astroboa.api.model.RepositoryUser; import org.betaconceptframework.astroboa.api.model.Space; import org.betaconceptframework.astroboa.api.model.definition.Localization; import org.betaconceptframework.astroboa.api.model.exception.CmsException; import org.betaconceptframework.astroboa.engine.database.dao.CmsRepositoryEntityAssociationDao; import org.betaconceptframework.astroboa.model.impl.ContentObjectImpl; import org.betaconceptframework.astroboa.model.impl.item.CmsBuiltInItem; import org.betaconceptframework.astroboa.util.CmsConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** * * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ public class SpaceUtils { final Logger logger = LoggerFactory.getLogger(SpaceUtils.class); @Autowired private CmsRepositoryEntityUtils cmsRepositoryEntityUtils; @Autowired private CmsLocalizationUtils cmsLocalizationUtils; @Autowired private CmsRepositoryEntityAssociationDao cmsRepositoryEntityAssociationDao; public Node addNewSpaceJcrNode(Node parentSpaceJcrNode, Space space, Session session, boolean useProvidedId, Context context) throws RepositoryException { Node spaceJcrNode = JcrNodeUtils.addSpaceNode(parentSpaceJcrNode, CmsBuiltInItem.Space.getJcrName()); cmsRepositoryEntityUtils.createCmsIdentifier(spaceJcrNode, space, useProvidedId); return populateSpaceJcrNode(space, session, spaceJcrNode,useProvidedId, context); } private Node populateSpaceJcrNode(Space space, Session session, Node spaceJcrNode, boolean useProvidedId, Context context) throws RepositoryException { //Update OwnerId updateOwner(space.getOwner(), spaceJcrNode, session, context); //Update Localized Labels updateLocalizedLabels(space, spaceJcrNode); //Update order updateOrder(space, spaceJcrNode); // Update updateName(space, spaceJcrNode); updateContentObjectReferencesForSpace(spaceJcrNode, (Space)space, session, context); // Save or update children saveOrUpdateChildren(space, session, spaceJcrNode, context); return spaceJcrNode; } private void saveOrUpdateChildren(Space space, Session session, Node spaceJcrNode, Context context) throws RepositoryException { if (space.isChildrenLoaded()){ List<Space> children = space.getChildren(); //Now insert new subTaxonomyNode if (CollectionUtils.isNotEmpty(children)){ for (Space child: children){ if (child.getId() != null){ updateSpace(session, child, spaceJcrNode, context); } else{ addNewSpaceJcrNode(spaceJcrNode, child, session, false, context); } } } } } public void updateName(Space space, Node spaceJcrNode) throws RepositoryException { if (space.getName() != null && ! StringUtils.equals(CmsBuiltInItem.OrganizationSpace.getLocalPart(), space.getName())) { if (!cmsRepositoryEntityUtils.isValidSystemName(space.getName())){ throw new RepositoryException("Space name '"+space.getName()+"' is not valid. It should match pattern "+CmsConstants.SYSTEM_NAME_REG_EXP); } spaceJcrNode.setProperty(CmsBuiltInItem.Name.getJcrName(), space.getName()); } else{ spaceJcrNode.setProperty(CmsBuiltInItem.Name.getJcrName(), JcrValueUtils.getJcrNull()); } } public void updateOrder(Space space, Node spaceJcrNode) throws RepositoryException { if (space.getOrder() != null) spaceJcrNode.setProperty(CmsBuiltInItem.Order.getJcrName(), space.getOrder()); else spaceJcrNode.setProperty(CmsBuiltInItem.Order.getJcrName(), JcrValueUtils.getJcrNull()); } public void updateLocalizedLabels(Localization localization, Node spaceJcrNode) throws RepositoryException { cmsLocalizationUtils.updateCmsLocalization(localization, spaceJcrNode); } public void updateOwner(RepositoryUser spaceOwner, Node spaceJcrNode, Session session, Context context) throws RepositoryException { //Owner is expected to exist //Therefore no further search in repository is necessary //Just update OwnerId value if (spaceOwner == null || StringUtils.isBlank(spaceOwner.getId())) throw new CmsException("TaxonomyNode must have an Owner defined"); //Update owner id only if existing owner id is not the same String newOwnerId = spaceOwner.getId(); if (!spaceJcrNode.hasProperty(CmsBuiltInItem.OwnerCmsIdentifier.getJcrName()) || !spaceJcrNode.getProperty(CmsBuiltInItem.OwnerCmsIdentifier.getJcrName()).getString().equals(newOwnerId)){ //Check that owner id does correspond to existing user if (cmsRepositoryEntityUtils.retrieveUniqueNodeForRepositoryUser(session, newOwnerId) ==null){ throw new CmsException("No repository user found with cms identifier "+ newOwnerId + ". ExternalId : "+ spaceOwner.getExternalId() + ", Label : "+ spaceOwner.getLabel()); } EntityAssociationUpdateHelper<RepositoryUser> repositoryUserAssociationUpdateHelper = new EntityAssociationUpdateHelper<RepositoryUser>(session,cmsRepositoryEntityAssociationDao, context); repositoryUserAssociationUpdateHelper.setReferrerCmsRepositoryEntityNode(spaceJcrNode); repositoryUserAssociationUpdateHelper.setReferrerPropertyName(CmsBuiltInItem.OwnerCmsIdentifier); repositoryUserAssociationUpdateHelper.setValuesToBeAdded(Arrays.asList(spaceOwner)); repositoryUserAssociationUpdateHelper.update(); } } public Node updateSpace(Session session, Space space, Node parentSpaceJcrNode, Context context) throws RepositoryException { Node spaceJcrNode = cmsRepositoryEntityUtils.retrieveUniqueNodeForSpace(session, space.getId()); if (spaceJcrNode == null){ if (StringUtils.equalsIgnoreCase(CmsBuiltInItem.OrganizationSpace.getLocalPart(), space.getName())){ spaceJcrNode = JcrNodeUtils.getOrganizationSpaceNode(session); } else if (space.getId() != null){ //User has specified an id for TaxonomyNode. Create a new one if(parentSpaceJcrNode == null){ parentSpaceJcrNode = retrieveParentSpaceNode(session, space); } return addNewSpaceJcrNode(parentSpaceJcrNode, space, session, true, context); } else throw new CmsException("Found no space with id "+space.getId()); } updateOwner(space.getOwner(), spaceJcrNode, session, context); updateLocalizedLabels(space, spaceJcrNode); updateName(space, spaceJcrNode); if (space.getParent() != null){ updateSpaceParent(space.getParent(), spaceJcrNode, session); } updateOrder(space, spaceJcrNode); updateContentObjectReferencesForSpace(spaceJcrNode, (Space) space, session, context); return spaceJcrNode; } private void updateContentObjectReferencesForSpace(Node spaceNode , Space space, Session session, Context context) throws RepositoryException { if (space.isContentObjectReferencesLoaded()) { List<ContentObject> contentObjects = new ArrayList<ContentObject>(); List<String> contentObjectReferences = space.getContentObjectReferences(); if (CollectionUtils.isNotEmpty(contentObjectReferences)) { for (String contentObjectReference: contentObjectReferences) { ContentObject contentObject = new ContentObjectImpl(); contentObject.setId(contentObjectReference); contentObjects.add(contentObject); } } EntityAssociationUpdateHelper<ContentObject> spaceUpdateHelper = new EntityAssociationUpdateHelper<ContentObject>(session,cmsRepositoryEntityAssociationDao, context); spaceUpdateHelper.setReferrerCmsRepositoryEntityNode(spaceNode); spaceUpdateHelper.setReferrerPropertyName(CmsBuiltInItem.ContentObjectReferences); spaceUpdateHelper.setReferrerPropertyNameMultivalue(true); spaceUpdateHelper.setValuesToBeAdded(contentObjects); spaceUpdateHelper.update(); } } public void updateSpaceParent(Space parentSpace, Node spaceJcrNode, Session session) throws RepositoryException { if (parentSpace == null) throw new CmsException("Invalid parent taxonomy tree node."); Node newParentSpaceJcrNode = cmsRepositoryEntityUtils.retrieveUniqueNodeForSpace(session, parentSpace.getId()); if (newParentSpaceJcrNode == null) { if (StringUtils.equalsIgnoreCase(CmsBuiltInItem.OrganizationSpace.getLocalPart(), parentSpace.getName())) { newParentSpaceJcrNode = JcrNodeUtils.getOrganizationSpaceNode(session); } else { throw new CmsException("Invalid parent space with id "+parentSpace.getId()); } } //New Parent's Primary Type can only be Space if (!newParentSpaceJcrNode.isNodeType(spaceJcrNode.getPrimaryNodeType().getName())) { throw new CmsException("Parent space can only be a space"); } //Change Parent only if current parent is not the same if (!spaceJcrNode.getParent().getIdentifier().equals(newParentSpaceJcrNode.getIdentifier())) session.move(spaceJcrNode.getPath(), newParentSpaceJcrNode.getPath()+CmsConstants.FORWARD_SLASH+spaceJcrNode.getName()); } public void removeSpaceJcrNode(Node spaceJcrNode, Session session, boolean removeJcrNode, Context context) throws RepositoryException{ EntityAssociationDeleteHelper<Space> entityAssociationDeleteHelper = new EntityAssociationDeleteHelper<Space>(session,cmsRepositoryEntityAssociationDao, context); removeSpaceFromAssociations(entityAssociationDeleteHelper, spaceJcrNode); NodeIterator children = null; if (spaceJcrNode.isNodeType(CmsBuiltInItem.Space.getJcrName())) children = spaceJcrNode.getNodes(CmsBuiltInItem.Space.getJcrName()); if (children != null){ while (children.hasNext()){ removeSpaceJcrNode(children.nextNode(), session, false, context); //Do not remove child jcr node. Its parent may be removed } } if (removeJcrNode){ spaceJcrNode.remove(); } } private void removeSpaceFromAssociations(EntityAssociationDeleteHelper<Space> entityAssociationDeleteHelper, Node spaceJcrNode) throws RepositoryException { entityAssociationDeleteHelper.setCmsRepositoryEntityIdToBeRemoved(cmsRepositoryEntityUtils.getCmsIdentifier(spaceJcrNode)); entityAssociationDeleteHelper.removeOrReplaceAllReferences(Space.class); } public Node retrieveParentSpaceNode(Session session, Space space) throws RepositoryException { Node spaceParent = null; if (space.getParent() != null){ if (StringUtils.equalsIgnoreCase(CmsBuiltInItem.OrganizationSpace.getLocalPart(), space.getParent().getName())){ spaceParent = JcrNodeUtils.getOrganizationSpaceNode(session); } else{ spaceParent = cmsRepositoryEntityUtils.retrieveUniqueNodeForSpace(session, space.getParent().getId()); } } if (spaceParent == null){ throw new CmsException("No parent is defined for space id :"+space.getId() + ", name : "+ space.getName()); } return spaceParent; } public void checkSpaceOwner(Space space, RepositoryUser systemUser, boolean replaceOwner) { if (space != null){ if ( replaceOwner || space.getOwner() == null || ( StringUtils.equals(space.getOwner().getExternalId(), CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID) && ! StringUtils.equals(space.getOwner().getId(), systemUser.getId()) ) ){ space.setOwner(systemUser); } if (space.isChildrenLoaded()){ List<Space> childSpaces = space.getChildren(); if (CollectionUtils.isNotEmpty(childSpaces)){ for (Space childSpace : childSpaces){ checkSpaceOwner(childSpace, systemUser,replaceOwner); } } } } } }