/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/
package org.infoglue.cms.controllers.kernel.impl.simple;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.PersistenceException;
import org.infoglue.cms.entities.content.ContentCategory;
import org.infoglue.cms.entities.content.ContentCategoryVO;
import org.infoglue.cms.entities.content.ContentVO;
import org.infoglue.cms.entities.content.ContentVersion;
import org.infoglue.cms.entities.content.ContentVersionVO;
import org.infoglue.cms.entities.content.SmallestContentVersionVO;
import org.infoglue.cms.entities.content.impl.simple.MediumContentVersionImpl;
import org.infoglue.cms.entities.kernel.BaseEntityVO;
import org.infoglue.cms.entities.management.AccessRight;
import org.infoglue.cms.entities.management.AccessRightVO;
import org.infoglue.cms.entities.management.ContentTypeDefinitionVO;
import org.infoglue.cms.entities.management.InterceptionPoint;
import org.infoglue.cms.entities.workflow.EventVO;
import org.infoglue.cms.exception.ConstraintException;
import org.infoglue.cms.exception.SystemException;
import org.infoglue.cms.security.InfoGluePrincipal;
import org.infoglue.cms.util.CmsPropertyHandler;
import org.infoglue.cms.util.ConstraintExceptionBuffer;
import org.infoglue.cms.util.DateHelper;
import org.infoglue.deliver.util.Timer;
public class ContentStateController extends BaseController
{
private final static Logger logger = Logger.getLogger(ContentStateController.class.getName());
public static final ContentCategoryController contentCategoryController = ContentCategoryController.getController();
public static final int OVERIDE_WORKING = 1;
public static final int LEAVE_WORKING = 2;
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static ContentVersionVO changeState(Integer oldContentVersionId, Integer stateId, String versionComment, boolean overrideVersionModifyer, InfoGluePrincipal infoGluePrincipal, Integer contentId, List resultingEvents) throws ConstraintException, SystemException
{
ContentVO contentVO = (contentId == null ? null : ContentController.getContentController().getContentVOWithId(contentId));
return changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, null, infoGluePrincipal, contentId, resultingEvents);
}
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static ContentVersionVO changeState(Integer oldContentVersionId, ContentVO contentVO, Integer stateId, String versionComment, boolean overrideVersionModifyer, InfoGluePrincipal infoGluePrincipal, Integer contentId, List resultingEvents) throws ConstraintException, SystemException
{
return changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, null, infoGluePrincipal, contentId, resultingEvents);
}
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static ContentVersionVO changeState(Integer oldContentVersionId, Integer stateId, String versionComment, boolean overrideVersionModifyer, String recipientFilter, InfoGluePrincipal infoGluePrincipal, Integer contentId, List resultingEvents) throws ConstraintException, SystemException
{
ContentVO contentVO = (contentId == null ? null : ContentController.getContentController().getContentVOWithId(contentId));
return changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, recipientFilter, infoGluePrincipal, contentId, resultingEvents);
}
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static ContentVersionVO changeState(Integer oldContentVersionId, Integer stateId, String versionComment, boolean overrideVersionModifyer, InfoGluePrincipal infoGluePrincipal, Integer contentId, Database db, List resultingEvents) throws ConstraintException, SystemException
{
ContentVO contentVO = ContentController.getContentController().getContentVOWithId(contentId, db);
ContentVersion newContentVersion = changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, null, infoGluePrincipal, contentId, db, resultingEvents);
return newContentVersion.getValueObject();
}
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static ContentVersionVO changeState(Integer oldContentVersionId, ContentVO contentVO, Integer stateId, String versionComment, boolean overrideVersionModifyer, String recipientFilter, InfoGluePrincipal infoGluePrincipal, Integer contentId, List resultingEvents) throws ConstraintException, SystemException
{
Database db = CastorDatabaseService.getDatabase();
ConstraintExceptionBuffer ceb = new ConstraintExceptionBuffer();
ContentVersionVO newContentVersionVO = null;
beginTransaction(db);
try
{
if(contentId == null)
{
SmallestContentVersionVO contentVersionVO = ContentVersionController.getContentVersionController().getSmallestContentVersionVOWithId(oldContentVersionId, db);
contentId = contentVersionVO.getContentId();
}
ContentVersion newContentVersion = changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, recipientFilter, infoGluePrincipal, contentId, db, resultingEvents);
if(newContentVersion != null)
newContentVersionVO = newContentVersion.getValueObject();
commitRegistryAwareTransaction(db);
}
catch(ConstraintException ce)
{
logger.error("An error occurred so we should not complete the transaction:" + ce.getMessage());
rollbackTransaction(db);
throw ce;
}
catch(Exception e)
{
logger.error("An error occurred so we should not complete the transaction:" + e, e);
rollbackTransaction(db);
throw new SystemException(e.getMessage());
}
return newContentVersionVO;
}
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static ContentVersion changeState(Integer oldContentVersionId, ContentVO contentVO, Integer stateId, String versionComment, boolean overrideVersionModifyer, InfoGluePrincipal infoGluePrincipal, Integer contentId, Database db, List resultingEvents) throws SystemException, ConstraintException
{
return changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, null, infoGluePrincipal, contentId, db, resultingEvents);
}
/**
* This method handles versioning and state-control of content.
* Se inline documentation for further explainations.
*/
public static MediumContentVersionImpl changeState(Integer oldContentVersionId, ContentVO contentVO, Integer stateId, String versionComment, boolean overrideVersionModifyer, String recipientFilter, InfoGluePrincipal infoGluePrincipal, Integer contentId, Database db, List resultingEvents) throws SystemException, ConstraintException
{
return changeState(oldContentVersionId, contentVO, stateId, versionComment, overrideVersionModifyer, recipientFilter, infoGluePrincipal, contentId, db, resultingEvents, null);
}
public static MediumContentVersionImpl changeState(Integer oldContentVersionId, ContentVO contentVO, Integer stateId, String versionComment, boolean overrideVersionModifyer, String recipientFilter, InfoGluePrincipal infoGluePrincipal, Integer contentId, Database db, List resultingEvents, Integer excludedAssetId) throws SystemException, ConstraintException
{
MediumContentVersionImpl newContentVersion = null;
try
{
//MediumContentVersionImpl oldContentVersion = ContentVersionController.getContentVersionController().getReadOnlyMediumContentVersionWithId(oldContentVersionId, db);
MediumContentVersionImpl oldContentVersion = ContentVersionController.getContentVersionController().getMediumContentVersionWithId(oldContentVersionId, db);
newContentVersion = oldContentVersion;
logger.info("oldContentVersion:" + oldContentVersion.getId());
//t.printElapsedTime("oldContentVersion");
if (contentId == null && contentVO != null)
contentId = contentVO.getContentId();
else if(contentId == null)
contentId = oldContentVersion.getValueObject().getContentId();
if(contentId != null && contentVO == null)
contentVO = ContentController.getContentController().getContentVOWithId(contentId, db);
boolean duplicateAssets = CmsPropertyHandler.getDuplicateAssetsBetweenVersions();
//Here we create a new version if it was a state-change back to working, it's a copy of the publish-version
if (stateId.intValue() == ContentVersionVO.WORKING_STATE.intValue())
{
logger.info("About to create a new working version");
ContentVersionVO newContentVersionVO = new ContentVersionVO();
newContentVersionVO.setStateId(stateId);
if(versionComment != null && !versionComment.equals(""))
newContentVersionVO.setVersionComment(versionComment);
else
newContentVersionVO.setVersionComment("New working version");
newContentVersionVO.setModifiedDateTime(DateHelper.getSecondPreciseDate());
if(overrideVersionModifyer)
newContentVersionVO.setVersionModifier(infoGluePrincipal.getName());
else
newContentVersionVO.setVersionModifier(oldContentVersion.getVersionModifier());
newContentVersionVO.setVersionValue(oldContentVersion.getVersionValue());
newContentVersion = ContentVersionController.getContentVersionController().createMedium(oldContentVersion, contentId, oldContentVersion.getValueObject().getLanguageId(), newContentVersionVO, oldContentVersion.getContentVersionId(), (oldContentVersion.getDigitalAssets().size() > 0), true, duplicateAssets, excludedAssetId, db);
//newContentVersion = ContentVersionController.getContentVersionController().create(contentId, oldContentVersion.getLanguage().getLanguageId(), newContentVersionVO, oldContentVersion.getContentVersionId(), true, duplicateAssets, excludedAssetId, db);
//ContentVersionController.getContentVersionController().copyDigitalAssets(oldContentVersion, newContentVersion, db);
if(contentVO.getIsProtected().equals(ContentVO.YES))
copyAccessRights(oldContentVersion.getId(), newContentVersion.getId(), db);
copyContentCategories(oldContentVersion.getId(), newContentVersion.getId(), db);
RegistryController.getController().updateContentVersionThreaded(newContentVersion.getValueObject(), null);
}
//If the user changes the state to publish we create a copy and set that copy to publish.
if (stateId.intValue() == ContentVersionVO.PUBLISH_STATE.intValue())
{
logger.info("About to copy the working copy to a publish-one");
//First we update the old working-version so it gets a comment
logger.info("Setting comment " + versionComment + " on " + oldContentVersion.getId());
//oldContentVersion.setVersionComment(versionComment);
if(CmsPropertyHandler.getUseApprovalFlow().equals("true"))
{
//Now we create a new version which is basically just a copy of the working-version
ContentVersionVO newContentVersionVO = new ContentVersionVO();
newContentVersionVO.setStateId(stateId);
newContentVersionVO.setVersionComment(versionComment);
newContentVersionVO.setModifiedDateTime(DateHelper.getSecondPreciseDate());
if(overrideVersionModifyer)
newContentVersionVO.setVersionModifier(infoGluePrincipal.getName());
else
newContentVersionVO.setVersionModifier(oldContentVersion.getVersionModifier());
newContentVersionVO.setVersionValue(oldContentVersion.getVersionValue());
newContentVersion = ContentVersionController.getContentVersionController().createMedium(oldContentVersion, contentId, oldContentVersion.getValueObject().getLanguageId(), newContentVersionVO, oldContentVersion.getContentVersionId(), (oldContentVersion.getDigitalAssets().size() > 0), false, duplicateAssets, excludedAssetId, db);
logger.info("Creating " + newContentVersion.getId());
//ContentVersionController.getContentVersionController().copyDigitalAssets(oldContentVersion, newContentVersion, db);
if(contentVO.getIsProtected().equals(ContentVO.YES))
copyAccessRights(oldContentVersion.getId(), newContentVersion.getId(), db);
copyContentCategories(oldContentVersion.getId(), newContentVersion.getId(), db);
//Creating the event that will notify the editor...
RegistryController.getController().updateContentVersionThreaded(newContentVersion.getValueObject(), null);
ContentTypeDefinitionVO metaInfoCTDVO = ContentTypeDefinitionController.getController().getContentTypeDefinitionVOWithName("Meta info");
if(contentVO.getContentTypeDefinitionId() != null && !contentVO.getContentTypeDefinitionId().equals(metaInfoCTDVO.getId()))
{
EventVO eventVO = new EventVO();
eventVO.setDescription(newContentVersion.getVersionComment());
eventVO.setEntityClass(ContentVersion.class.getName());
eventVO.setEntityId(new Integer(newContentVersion.getId().intValue()));
eventVO.setName(contentVO.getName());
eventVO.setTypeId(EventVO.PUBLISH);
eventVO = EventController.create(eventVO, contentVO.getRepositoryId(), infoGluePrincipal, db);
resultingEvents.add(eventVO);
}
}
else
{
oldContentVersion = ContentVersionController.getContentVersionController().getMediumContentVersionWithId(oldContentVersionId, db);
oldContentVersion.setVersionComment(versionComment);
EventVO eventVO = new EventVO();
eventVO.setDescription(versionComment);
eventVO.setEntityClass(ContentVersion.class.getName());
eventVO.setEntityId(new Integer(newContentVersion.getId().intValue()));
eventVO.setName(contentVO.getName());
eventVO.setTypeId(EventVO.PUBLISH);
eventVO = EventController.create(eventVO, contentVO.getRepositoryId(), infoGluePrincipal, db);
resultingEvents.add(eventVO);
}
//if(recipientFilter != null && !recipientFilter.equals(""))
// PublicationController.mailPublishNotification(resultingEvents, contentVO.getRepositoryId(), infoGluePrincipal, recipientFilter, db);
}
//If the user in the publish-app publishes a publish-version we change state to published.
if (stateId.intValue() == ContentVersionVO.PUBLISHED_STATE.intValue())
{
oldContentVersion = ContentVersionController.getContentVersionController().getMediumContentVersionWithId(oldContentVersionId, db);
logger.info("About to publish an existing version:" + oldContentVersion.getId() + ":" + oldContentVersion.getStateId());
Integer oldContentVersionStateId = oldContentVersion.getStateId();
oldContentVersion.setStateId(stateId);
oldContentVersion.setIsActive(new Boolean(true));
//New logic to add meta data in some cases... ugly but needed if users are removed.
insertIGMetaDataAttributes(oldContentVersion, infoGluePrincipal);
//End new logic
newContentVersion = oldContentVersion;
//Creating the event that will notify the editor...
if(oldContentVersionStateId.intValue() == ContentVersionVO.WORKING_STATE.intValue())
{
ContentTypeDefinitionVO metaInfoCTDVO = ContentTypeDefinitionController.getController().getContentTypeDefinitionVOWithName("Meta info");
if(contentVO.getContentTypeDefinitionId() != null && !contentVO.getContentTypeDefinitionId().equals(metaInfoCTDVO.getId()))
{
EventVO eventVO = new EventVO();
eventVO.setDescription(newContentVersion.getVersionComment());
eventVO.setEntityClass(ContentVersion.class.getName());
eventVO.setEntityId(new Integer(newContentVersion.getId().intValue()));
eventVO.setName(contentVO.getName());
eventVO.setTypeId(EventVO.PUBLISH);
eventVO = EventController.create(eventVO, contentVO.getRepositoryId(), infoGluePrincipal, db);
resultingEvents.add(eventVO);
}
}
}
}
catch (ConstraintException ce)
{
logger.error("An error occurred so we should not complete the transaction:" + ce.getMessage());
throw ce;
}
catch (Exception e)
{
logger.error("An error occurred so we should not complete the transaction:" + e, e);
throw new SystemException(e.getMessage());
}
return newContentVersion;
}
/**
* This method assigns the same access rights as the old content-version has.
*/
private static void copyAccessRights(Integer originalContentVersionId, Integer newContentVersionId, Database db) throws ConstraintException, SystemException, Exception
{
List interceptionPointList = InterceptionPointController.getController().getInterceptionPointList("ContentVersion", db);
logger.info("interceptionPointList:" + interceptionPointList.size());
Iterator interceptionPointListIterator = interceptionPointList.iterator();
while(interceptionPointListIterator.hasNext())
{
InterceptionPoint interceptionPoint = (InterceptionPoint)interceptionPointListIterator.next();
List accessRightList = AccessRightController.getController().getAccessRightListForEntity(interceptionPoint.getId(), originalContentVersionId.toString(), db);
logger.info("accessRightList:" + accessRightList.size());
Iterator accessRightListIterator = accessRightList.iterator();
while(accessRightListIterator.hasNext())
{
AccessRight accessRight = (AccessRight)accessRightListIterator.next();
logger.info("accessRight:" + accessRight.getId());
AccessRightVO copiedAccessRight = accessRight.getValueObject().createCopy(); //.getValueObject();
copiedAccessRight.setParameters(newContentVersionId.toString());
AccessRightController.getController().create(copiedAccessRight, interceptionPoint, db);
}
}
}
/**
* Makes copies of the ContentCategories for the old ContentVersion so the new ContentVersion
* still has references to them.
*
* @param originalContentVersion
* @param newContentVersion
* @param db The Database to use
* @throws SystemException If an error happens
*/
private static void copyContentCategories(Integer originalContentVersion, Integer newContentVersionId, Database db) throws SystemException, PersistenceException
{
//if(originalContentVersion.getContentCategories().size() > 0)
//{
List orignals = contentCategoryController.findByContentVersion(originalContentVersion, db);
logger.info("orignals:" + orignals.size() + " on " + originalContentVersion);
for (Iterator iter = orignals.iterator(); iter.hasNext();)
{
ContentCategory contentCategory = (ContentCategory)iter.next();
ContentCategoryVO vo = new ContentCategoryVO();
vo.setAttributeName(contentCategory.getAttributeName());
vo.setCategory(contentCategory.getCategory().getValueObject());
vo.setContentVersionId(newContentVersionId);
ContentCategory newContentCategory = contentCategoryController.createWithDatabase(vo, db);
//newContentCategory
}
//}
}
/**
* New logic to add meta data in some cases... ugly but needed if users are removed.
*/
private static void insertIGMetaDataAttributes(ContentVersion version, InfoGluePrincipal infoGluePrincipal)
{
String authorXML = "<IGAuthorFullName><![CDATA[" + infoGluePrincipal.getFirstName() + " " + infoGluePrincipal.getLastName() + "]]></IGAuthorFullName><IGAuthorEmail><![CDATA[" + infoGluePrincipal.getEmail() + "]]></IGAuthorEmail>";
String oldVersionValue = version.getVersionValue();
if(oldVersionValue.indexOf("<IGAuthorFullName>") > -1)
oldVersionValue = oldVersionValue.replaceAll("<IGAuthorFullName>.*?</IGAuthorEmail>", authorXML);
else
oldVersionValue = oldVersionValue.replaceAll("</attributes>", authorXML + "</attributes>");
version.setVersionValue(oldVersionValue);
}
/**
* This method should never be called.
*/
public BaseEntityVO getNewVO()
{
return null;
}
}