/* ===============================================================================
*
* 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.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.OQLQuery;
import org.exolab.castor.jdo.QueryResults;
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.kernel.BaseEntityVO;
import org.infoglue.cms.entities.management.Repository;
import org.infoglue.cms.entities.management.impl.simple.RepositoryImpl;
import org.infoglue.cms.entities.structure.SiteNodeVO;
import org.infoglue.cms.entities.structure.SiteNodeVersion;
import org.infoglue.cms.entities.structure.SiteNodeVersionVO;
import org.infoglue.cms.entities.workflow.Event;
import org.infoglue.cms.entities.workflow.EventVO;
import org.infoglue.cms.entities.workflow.impl.simple.EventImpl;
import org.infoglue.cms.exception.Bug;
import org.infoglue.cms.exception.SystemException;
import org.infoglue.cms.security.InfoGlueGroup;
import org.infoglue.cms.security.InfoGluePrincipal;
import org.infoglue.deliver.util.Timer;
/**
* @author Mattias Bogeblad
*
* This class implements all operations we can do on the cmEvent-entity.
*/
public class EventController extends BaseController
{
private final static Logger logger = Logger.getLogger(EventController.class.getName());
/**
* Gets the eventVO in a readonly transaction.
*/
public static EventVO getEventVOWithId(Integer eventId) throws SystemException, Bug
{
return (EventVO) getVOWithId(EventImpl.class, eventId);
}
/**
* Gets the event in the given transaction.
*/
public static Event getEventWithId(Integer eventId, Database db) throws SystemException, Bug
{
return (Event) getObjectWithId(EventImpl.class, eventId, db);
}
/**
* Gets all events in a read only transaction.
*/
public List getEventVOList() throws SystemException, Bug
{
return getAllVOObjects(EventImpl.class, "eventId");
}
/**
* Creates a new Event with the values in the eventVO sent in.
*/
public static EventVO create(EventVO eventVO, Integer repositoryId, InfoGluePrincipal infoGluePrincipal, Database db) throws SystemException
{
Event event = new EventImpl();
event.setValueObject(eventVO);
event.setRepositoryId(repositoryId);
event.setCreator(infoGluePrincipal.getName());
try
{
db.create(event);
}
catch(Exception e)
{
logger.error("An error occurred so we should not complete the transaction:" + e, e);
throw new SystemException(e.getMessage());
}
return event.getValueObject();
}
/**
* Creates a new Event with the values in the eventVO sent in in a new transaction.
*/
public static EventVO create(EventVO eventVO, Integer repositoryId, InfoGluePrincipal infoGluePrincipal) throws SystemException
{
Event event = null;
Database db = CastorDatabaseService.getDatabase();
beginTransaction(db);
try
{
event = new EventImpl();
event.setValueObject(eventVO);
event.setRepositoryId(repositoryId);
event.setCreator(infoGluePrincipal.getName());
db.create(event);
commitTransaction(db);
}
catch(Exception e)
{
logger.error("An error occurred so we should not completes the transaction:" + e, e);
rollbackTransaction(db);
throw new SystemException(e.getMessage());
}
return event.getValueObject();
}
/**
* This method removes an event from the database.
*/
public static void delete(EventVO eventVO) throws SystemException
{
deleteEntity(EventImpl.class, eventVO.getEventId());
}
/**
* This method removes an event from the database.
*/
public static void delete(Event event, Database db) throws SystemException
{
try
{
db.remove(event);
}
catch (Exception e)
{
throw new SystemException(e);
}
}
/**
* This method updates an event.
*/
public static EventVO update(EventVO eventVO) throws SystemException
{
return (EventVO) updateEntity(EventImpl.class, eventVO);
}
/**
* Returns a list of events currently available for the certain entity.
*/
public static List<EventVO> getEventVOListForEntity(String entityClass, Integer entityId) throws SystemException, Bug
{
Timer t = new Timer();
List<EventVO> events = new ArrayList<EventVO>();
Database db = CastorDatabaseService.getDatabase();
beginTransaction(db);
try
{
OQLQuery oql = db.getOQLQuery("SELECT e FROM org.infoglue.cms.entities.workflow.impl.simple.SmallEventImpl e WHERE e.entityClass = $1 AND e.entityId = $2");
oql.bind(entityClass);
oql.bind(entityId);
QueryResults results = oql.execute();
while (results.hasMore())
{
Event event = (Event)results.next();
events.add(event.getValueObject());
}
results.close();
oql.close();
commitTransaction(db);
}
catch (Exception e)
{
logger.error("An error occurred so we should not completes the transaction:" + e, e);
rollbackTransaction(db);
throw new SystemException(e.getMessage());
}
t.printElapsedTime("getEventVOListForEntity took", 50);
return events;
}
/**
* Returns a list of events with either publish or unpublish-state currently available for the repository stated.
*/
public static List getPublicationEventVOListForRepository(Integer repositoryId) throws SystemException, Bug
{
return getPublicationEventVOListForRepository(repositoryId, null, null, false);
}
/**
* Returns a list of events with either publish or unpublish-state currently available for the repository stated.
*/
public static List<Event> getPublicationEventVOListForRepository(Integer repositoryId, Database db) throws Exception
{
List<Event> events = new ArrayList<Event>();
Timer t = new Timer();
OQLQuery oql = db.getOQLQuery( "SELECT e FROM org.infoglue.cms.entities.workflow.impl.simple.EventImpl e WHERE (e.typeId = $1 OR e.typeId = $2) AND e.repositoryId = $3 ORDER BY e.eventId desc");
oql.bind(EventVO.PUBLISH);
oql.bind(EventVO.UNPUBLISH_LATEST);
oql.bind(repositoryId);
//logger.info("Fetching entity in read/write mode" + repositoryId);
QueryResults results = oql.execute();
while (results.hasMore())
{
Event event = (Event)results.next();
events.add(event);
}
results.close();
oql.close();
t.printElapsedTime("getPublicationEventVOListForRepository took", 50);
return events;
}
/**
* Returns a list of events with either publish or unpublish-state currently available for the repository stated.
*/
public static Map<Integer,List<EventVO>> getPublicationRepositoryEvents() throws SystemException, Bug
{
Map<Integer,List<EventVO>> repoEvents = new HashMap<Integer,List<EventVO>>();
boolean hasBrokenItems = false;
Database db = CastorDatabaseService.getDatabase();
beginTransaction(db);
try
{
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, -12);
OQLQuery oql = db.getOQLQuery( "SELECT e FROM org.infoglue.cms.entities.workflow.impl.simple.EventImpl e WHERE (e.typeId = $1 OR e.typeId = $2) AND e.creationDateTime > $3 ORDER BY e.eventId desc LIMIT $4");
oql.bind(EventVO.PUBLISH);
oql.bind(EventVO.UNPUBLISH_LATEST);
oql.bind(cal.getTime());
oql.bind(1000);
//logger.info("Fetching entity in read/write mode" + repositoryId);
QueryResults results = oql.execute(Database.READONLY);
while (results.hasMore())
{
Event event = (Event)results.next();
if(event.getRepositoryId() != null)
{
List<EventVO> events = repoEvents.get(event.getRepositoryId());
if(events == null)
{
events = new ArrayList<EventVO>();
repoEvents.put(event.getRepositoryId(), events);
}
events.add(event.getValueObject());
}
else
System.out.println("Skipping event as it does not belong to a repo...:" + event.getId());
}
results.close();
oql.close();
commitTransaction(db);
}
catch(Exception e)
{
logger.error("An error occurred so we should not completes the transaction:" + e, e);
rollbackTransaction(db);
throw new SystemException(e.getMessage());
}
return repoEvents;
}
/**
* Returns a list of events with either publish or unpublish-state currently available for the repository stated.
*/
public static List getPublicationEventVOListForRepository(Integer repositoryId, InfoGluePrincipal principal, String filter, boolean validate) throws SystemException, Bug
{
List events = new ArrayList();
boolean hasBrokenItems = false;
Database db = CastorDatabaseService.getDatabase();
beginTransaction(db);
try
{
OQLQuery oql = db.getOQLQuery( "SELECT e FROM org.infoglue.cms.entities.workflow.impl.simple.EventImpl e WHERE (e.typeId = $1 OR e.typeId = $2) AND e.repositoryId = $3 ORDER BY e.eventId desc");
oql.bind(EventVO.PUBLISH);
oql.bind(EventVO.UNPUBLISH_LATEST);
oql.bind(repositoryId);
//logger.info("Fetching entity in read/write mode" + repositoryId);
QueryResults results = oql.execute(Database.READONLY);
while (results.hasMore())
{
Event event = (Event)results.next();
//logger.warn("event:" + event.getId());
//logger.warn("entityClass:" + event.getEntityClass());
//logger.warn("entityId:" + event.getEntityId());
boolean isValid = true;
if(validate)
{
try
{
if(event.getEntityClass().equalsIgnoreCase(ContentVersion.class.getName()))
{
//ContentVersion contentVersion = null;
ContentVersionVO contentVersionVO = null;
ContentVO contentVO = null;
try
{
contentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(event.getEntityId(), db);
//contentVersion = ContentVersionController.getContentVersionController().getContentVersionWithId(event.getEntityId(), db);
if(contentVersionVO != null && contentVersionVO.getContentId() != null)
contentVO = ContentController.getContentController().getContentVOWithId(contentVersionVO.getContentId(), db);
}
catch(SystemException e)
{
hasBrokenItems = true;
throw e;
}
if(contentVersionVO == null || contentVO == null)
{
isValid = false;
hasBrokenItems = true;
}
else
{
if(principal != null && filter != null && filter.equalsIgnoreCase("groupBased"))
{
String versionModifier = contentVersionVO.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(principal.getGroups().contains(group))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
else if(principal != null && filter != null && filter.indexOf("groupNameBased_") > -1)
{
String versionModifier = contentVersionVO.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
String groupName = filter.substring(filter.indexOf("_") + 1);
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(groupName.equalsIgnoreCase(group.getName()))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
}
}
else if(event.getEntityClass().equalsIgnoreCase(SiteNodeVersion.class.getName()))
{
SiteNodeVersionVO siteNodeVersion = null;
SiteNodeVO siteNode = null;
try
{
siteNodeVersion = SiteNodeVersionController.getController().getSiteNodeVersionVOWithId(event.getEntityId(), db);
//siteNodeVersion = SiteNodeVersionController.getController().getSiteNodeVersionWithIdAsReadOnly(event.getEntityId(), db);
if(siteNodeVersion.getSiteNodeId() != null)
siteNode = SiteNodeController.getController().getSiteNodeVOWithId(siteNodeVersion.getSiteNodeId(), db);
}
catch(SystemException e)
{
hasBrokenItems = true;
throw e;
}
if(siteNodeVersion == null || siteNode == null)
{
hasBrokenItems = true;
isValid = false;
}
else
{
if(principal != null && filter != null && filter.equalsIgnoreCase("groupBased"))
{
String versionModifier = siteNodeVersion.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(principal.getGroups().contains(group))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
else if(principal != null && filter != null && filter.indexOf("groupNameBased_") > -1)
{
String versionModifier = siteNodeVersion.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
String groupName = filter.substring(filter.indexOf("_") + 1);
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(groupName.equalsIgnoreCase(group.getName()))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
}
}
}
catch(Exception e)
{
isValid = false;
hasBrokenItems = true;
}
}
if(isValid && !hasBrokenItems)
events.add(event.getValueObject());
}
results.close();
oql.close();
commitTransaction(db);
}
catch(Exception e)
{
logger.error("An error occurred so we should not completes the transaction:" + e, e);
rollbackTransaction(db);
throw new SystemException(e.getMessage());
}
if(hasBrokenItems)
{
cleanPublicationEventVOListForRepository(repositoryId, principal, filter);
events = getPublicationEventVOListForRepository(repositoryId, principal, filter, validate);
}
return events;
}
/**
* Returns a list of events with either publish or unpublish-state currently available for the repository stated.
*/
public static void cleanPublicationEventVOListForRepository(Integer repositoryId, InfoGluePrincipal principal, String filter) throws SystemException, Bug
{
Database db = CastorDatabaseService.getDatabase();
beginTransaction(db);
try
{
OQLQuery oql = db.getOQLQuery( "SELECT e FROM org.infoglue.cms.entities.workflow.impl.simple.EventImpl e WHERE (e.typeId = $1 OR e.typeId = $2) AND e.repositoryId = $3 ORDER BY e.eventId desc");
oql.bind(EventVO.PUBLISH);
oql.bind(EventVO.UNPUBLISH_LATEST);
oql.bind(repositoryId);
//logger.info("Fetching entity in read/write mode" + repositoryId);
QueryResults results = oql.execute();
while (results.hasMore())
{
Event event = (Event)results.next();
boolean isBroken = false;
boolean isValid = true;
try
{
if(event.getEntityClass().equalsIgnoreCase(ContentVersion.class.getName()))
{
ContentVersionVO contentVersionVO = null;
ContentVO contentVO = null;
try
{
contentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(event.getEntityId(), db);
//contentVersion = ContentVersionController.getContentVersionController().getContentVersionWithId(event.getEntityId(), db);
if(contentVersionVO != null && contentVersionVO.getContentId() != null)
contentVO = ContentController.getContentController().getContentVOWithId(contentVersionVO.getContentId(), db);
}
catch(SystemException e)
{
isBroken = true;
throw e;
}
if(contentVersionVO == null || contentVO == null)
{
isBroken = true;
isValid = false;
try
{
ContentVersion contentVersion = ContentVersionController.getContentVersionController().getContentVersionWithId(event.getEntityId(), db);
ContentVersionController.getContentVersionController().delete(contentVersion, db);
}
catch (Exception e)
{
logger.error("Error deleting contentVersion which lacked content:" + e.getMessage(), e);
}
}
else
{
if(principal != null && filter != null && filter.equalsIgnoreCase("groupBased"))
{
String versionModifier = contentVersionVO.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(principal.getGroups().contains(group))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
else if(principal != null && filter != null && filter.indexOf("groupNameBased_") > -1)
{
String versionModifier = contentVersionVO.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
String groupName = filter.substring(filter.indexOf("_") + 1);
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(groupName.equalsIgnoreCase(group.getName()))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
}
}
else if(event.getEntityClass().equalsIgnoreCase(SiteNodeVersion.class.getName()))
{
SiteNodeVersionVO siteNodeVersion = null;
SiteNodeVO siteNode = null;
try
{
siteNodeVersion = SiteNodeVersionController.getController().getSiteNodeVersionVOWithId(event.getEntityId(), db);
if(siteNodeVersion != null && siteNodeVersion.getSiteNodeId() != null)
siteNode = SiteNodeController.getController().getSiteNodeVOWithId(siteNodeVersion.getSiteNodeId(), db);
}
catch(SystemException e)
{
isBroken = true;
throw e;
}
if(siteNodeVersion == null || siteNode == null)
{
isBroken = true;
isValid = false;
SiteNodeVersionController.getController().delete(siteNodeVersion.getId(), db);
}
else
{
if(principal != null && filter != null && filter.equalsIgnoreCase("groupBased"))
{
String versionModifier = siteNodeVersion.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(principal.getGroups().contains(group))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
else if(principal != null && filter != null && filter.indexOf("groupNameBased_") > -1)
{
String versionModifier = siteNodeVersion.getVersionModifier();
if(versionModifier != null)
{
InfoGluePrincipal versionModifierPrincipal = UserControllerProxy.getController(db).getUser(versionModifier);
if(versionModifierPrincipal != null)
{
boolean hasGroup = false;
String groupName = filter.substring(filter.indexOf("_") + 1);
List groups = versionModifierPrincipal.getGroups();
Iterator groupsIterator = groups.iterator();
while(groupsIterator.hasNext())
{
InfoGlueGroup group = (InfoGlueGroup)groupsIterator.next();
if(groupName.equalsIgnoreCase(group.getName()))
hasGroup = true;
}
if(!hasGroup)
isValid = false;
}
}
}
}
}
}
catch(Exception e)
{
isValid = false;
}
if(isBroken)
delete(event, db);
}
results.close();
oql.close();
commitTransaction(db);
}
catch(Exception e)
{
logger.error("An error occurred so we should not completes the transaction:" + e, e);
rollbackTransaction(db);
throw new SystemException(e.getMessage());
}
}
/**
* This is a method that gives the user back an newly initialized ValueObject for this entity that the controller
* is handling.
*/
public BaseEntityVO getNewVO()
{
return new EventVO();
}
}