package org.nightlabs.jfire.entityuserset.ui;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.jdo.FetchPlan;
import javax.jdo.JDOHelper;
import org.nightlabs.jdo.NLJDOHelper;
import org.nightlabs.jfire.entityuserset.AuthorizedObjectRef;
import org.nightlabs.jfire.entityuserset.EntityRef;
import org.nightlabs.jfire.entityuserset.EntityUserSet;
import org.nightlabs.jfire.entityuserset.dao.EntityUserSetDAO;
import org.nightlabs.jfire.entityuserset.id.EntityUserSetID;
import org.nightlabs.jfire.entityuserset.ui.resource.Messages;
import org.nightlabs.jfire.security.AuthorizedObject;
import org.nightlabs.jfire.security.UserLocal;
import org.nightlabs.jfire.security.UserSecurityGroup;
import org.nightlabs.jfire.security.dao.AuthorizedObjectDAO;
import org.nightlabs.jfire.security.id.AuthorizedObjectID;
import org.nightlabs.progress.ProgressMonitor;
import org.nightlabs.progress.SubProgressMonitor;
import org.nightlabs.util.CollectionUtil;
/**
* @author Daniel Mazurek - Daniel.Mazurek [dot] nightlabs [dot] de
*
*/
public abstract class EntityUserSetPageControllerHelper<Entity>
{
private static final String[] FETCH_GROUPS_ENTITY_USER_SET = {
FetchPlan.DEFAULT,
EntityUserSet.FETCH_GROUP_NAME,
EntityUserSet.FETCH_GROUP_DESCRIPTION,
EntityUserSet.FETCH_GROUP_AUTHORIZED_OBJECT_REFS,
AuthorizedObjectRef.FETCH_GROUP_ENTITY_REFS
};
private static final String[] FETCH_GROUPS_AUTHORIZED_OBJECT = {
FetchPlan.DEFAULT,
AuthorizedObject.FETCH_GROUP_NAME,
AuthorizedObject.FETCH_GROUP_DESCRIPTION,
UserLocal.FETCH_GROUP_USER,
UserLocal.FETCH_GROUP_USER_SECURITY_GROUPS,
UserSecurityGroup.FETCH_GROUP_MEMBERS
};
/**
* The {@link #load(EntityUserSetID, EntityUserSet, ProgressMonitor)} method has been called (and is finished).
* The loaded {@link EntityUserSet} can be accessed by {@link PropertyChangeEvent#getNewValue()}.
*/
public static final String PROPERTY_NAME_ENTITY_USER_SET_LOADED = "entityUserSetLoaded"; //$NON-NLS-1$
/**
* A {@link PropertyChangeEvent} with this property name is fired, when a authorizedObject has been removed from the
* currently managed {@link EntityUserSet}. The affected authorizedObject object can be accessed by
* {@link PropertyChangeEvent#getNewValue()}.
*/
public static final String PROPERTY_NAME_USER_REMOVED = "authorizedObjectRemoved"; //$NON-NLS-1$
/**
* A {@link PropertyChangeEvent} with this property name is fired, when a authorizedObject has been added to the
* currently managed {@link EntityUserSet}. The affected authorizedObject object can be accessed by
* {@link PropertyChangeEvent#getNewValue()}.
*/
public static final String PROPERTY_NAME_USER_ADDED = "authorizedObjectAdded"; //$NON-NLS-1$
/**
* A {@link PropertyChangeEvent} with this property name is fired, when an Entity has been added to
* the current selected authorizedObject of the currently managed {@link EntityUserSet}.
* The affected entity object can be accessed by {@link PropertyChangeEvent#getNewValue()}.
*/
public static final String PROPERTY_NAME_ENTITY_ADDED_TO_AUTHORIZED_OBJECT = "entityAdded"; //$NON-NLS-1$
/**
* A {@link PropertyChangeEvent} with this property name is fired, when an Entity has been removed from
* the current selected authorizedObject of the currently managed {@link EntityUserSet}.
* The affected entity object can be accessed by {@link PropertyChangeEvent#getNewValue()}.
*/
public static final String PROPERTY_NAME_ENTITY_REMOVED_TO_AUTHORIZED_OBJECT = "entityRemoved"; //$NON-NLS-1$
private PropertyChangeSupport propertyChangeSupport;
private EntityUserSetID entityUserSetID;
private EntityUserSet<Entity> entityUserSet;
private String[] entityUserSetFetchGroups;
private Map<AuthorizedObject, Boolean> authorizedObjects;
private Map<AuthorizedObjectID, Map<Entity, Boolean>> authorizedObjectIDToEntities;
private boolean loaded = false;
private volatile InheritedEntityUserSetResolver<Entity> inheritedEntityUserSetResolver;
// private Inheritable inheritable;
public EntityUserSetPageControllerHelper() {
super();
propertyChangeSupport = new PropertyChangeSupport(this);
}
public EntityUserSet<Entity> getEntityUserSet() {
checkLoaded();
return entityUserSet;
}
public EntityUserSetID getEntityUserSetID() {
checkLoaded();
return entityUserSetID;
}
public Map<AuthorizedObject, Boolean> getAuthorizedObjects() {
checkLoaded();
return authorizedObjects;
}
public Map<Entity, Boolean> getEntities(AuthorizedObject authorizedObject) {
checkLoaded();
return authorizedObjectIDToEntities.get(JDOHelper.getObjectId(authorizedObject));
}
public void addAuthorizedObject(AuthorizedObject authorizedObject) {
checkLoaded();
authorizedObjects.put(authorizedObject, Boolean.TRUE);
authorizedObjectIDToEntities.put((AuthorizedObjectID) JDOHelper.getObjectId(authorizedObject), new HashMap<Entity, Boolean>());
propertyChangeSupport.firePropertyChange(PROPERTY_NAME_USER_ADDED, null, authorizedObject);
}
public void removeAuthorizedObject(AuthorizedObject authorizedObject) {
checkLoaded();
authorizedObjects.put(authorizedObject, Boolean.FALSE);
authorizedObjectIDToEntities.remove(JDOHelper.getObjectId(authorizedObject));
propertyChangeSupport.firePropertyChange(PROPERTY_NAME_USER_REMOVED, null, authorizedObject);
}
public void addEntityToAuthorizedObject(Entity entity, AuthorizedObject authorizedObject) {
checkLoaded();
Map<Entity, Boolean> entityToAssignment = authorizedObjectIDToEntities.get(JDOHelper.getObjectId(authorizedObject));
if (entityToAssignment != null) {
entityToAssignment.put(entity, Boolean.TRUE);
propertyChangeSupport.firePropertyChange(PROPERTY_NAME_ENTITY_ADDED_TO_AUTHORIZED_OBJECT, null, entity);
}
}
public void removeEntityFromAuthorizedObject(Entity entity, AuthorizedObject authorizedObject) {
checkLoaded();
Map<Entity, Boolean> entityToAssignment = authorizedObjectIDToEntities.get(JDOHelper.getObjectId(authorizedObject));
if (entityToAssignment != null) {
entityToAssignment.put(entity, Boolean.FALSE);
propertyChangeSupport.firePropertyChange(PROPERTY_NAME_ENTITY_REMOVED_TO_AUTHORIZED_OBJECT, null, entity);
}
}
protected void checkLoaded() {
if (!loaded) {
throw new IllegalStateException("The method load(EntityUserSetID, EntityUserSet<Entity>, ProgressMonitor) has not been called yet, first call this method before calling other methods."); //$NON-NLS-1$
}
}
/**
* Get the current {@link InheritedEntityUserSetResolver} for this helper.
* Note, that this method might return <code>null</code>, check {@link #isManageInheritance()}
* to see if this helper manages inheritance.
* @return The current instance of {@link InheritedEntityUserSetResolver} or <code>null</code> if {@link #isManageInheritance()} is <code>false</code>.
*/
public InheritedEntityUserSetResolver<Entity> getInheritedEntityUserSetResolver()
{
if (inheritedEntityUserSetResolver == null) {
synchronized (this) {
inheritedEntityUserSetResolver = createInheritedEntityUserSetResolver();
}
}
return inheritedEntityUserSetResolver;
}
/**
* Return the fetch groups which should be used for loading the entities.
* This fetch group should be used inside the implementation of {@link #loadEntities(ProgressMonitor)}.
*
* @return the fetch groups which should be used for loading the entities
*/
protected abstract String[] getEntityFetchGroups();
/**
* Loads a {@link Collection} containing all necessary instances of Entity which should be selectable.
*
* @param monitor the {@link ProgressMonitor} to display the progress of loading.
* @return a {@link Collection} containing all necessary instances of Entity which should be selectable.
*/
protected abstract Collection<Entity> loadEntities(ProgressMonitor monitor);
/**
* Creates an implementation of {@link InheritedEntityUserSetResolver} for thsi controller.
* @return the implementation of {@link InheritedEntityUserSetResolver} for this controller.
*/
protected abstract InheritedEntityUserSetResolver<Entity> createInheritedEntityUserSetResolver();
/**
* Creates a new instance of an {@link EntityUserSet} for the entity type..
* @return a new {@link EntityUserSet} for the entity type.
*/
protected abstract EntityUserSet<Entity> createEntityUserSet();
/**
* Returns the {@link Class} of the entity.
* @return the class of the entity.
*/
protected abstract Class<Entity> getEntityClass();
/**
* Returns the name of the {@link EntityUserSet} which should be used in the UI.
* @return the name of the {@link EntityUserSet} which should be used in the UI.
*/
public abstract String getEntityUserSetName();
/**
* Loads the {@link EntityUserSet} and the fills up the corresponding data.
*
* @param entityUserSetID the {@link EntityUserSetID} to load the {@link EntityUserSet} for and populate the controller
* with the necessary data. (may be null, if newEntityUserSet is not null)
* @param newEntityUserSet the newly created EntityUserSet (may be null, if entityUserSetID is not null).
* @param monitor the {@link ProgressMonitor} to display the progress of loading.
*/
public void load(EntityUserSetID entityUserSetID, EntityUserSet<Entity> newEntityUserSet, ProgressMonitor monitor)
{
monitor.beginTask(Messages.getString("org.nightlabs.jfire.entityuserset.ui.EntityUserSetPageControllerHelper.task.loadEntityUserSet"), 100); //$NON-NLS-1$
try {
authorizedObjects = new HashMap<AuthorizedObject, Boolean>();
authorizedObjectIDToEntities = new HashMap<AuthorizedObjectID, Map<Entity,Boolean>>();
this.entityUserSetID = null;
this.entityUserSet = null;
if (entityUserSetID != null) {
this.entityUserSetID = entityUserSetID;
entityUserSet = EntityUserSetDAO.sharedInstance().getEntityUserSet(
entityUserSetID, getEntityUserSetFetchGroups(),
NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new SubProgressMonitor(monitor, 30)
);
}
else if (newEntityUserSet != null) {
entityUserSet = newEntityUserSet;
this.entityUserSetID = EntityUserSetID.create(entityUserSet.getOrganisationID(),
entityUserSet.getEntityClassName(), entityUserSet.getEntityUserSetID());
}
if (entityUserSet != null)
{
Collection<AuthorizedObject> authorizedObjects = AuthorizedObjectDAO.sharedInstance().getAuthorizedObjects(
FETCH_GROUPS_AUTHORIZED_OBJECT,
NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT,
new SubProgressMonitor(monitor, 35));
Collection<Entity> entities = loadEntities(new SubProgressMonitor(monitor, 35));
for (AuthorizedObject authorizedObject : authorizedObjects) {
AuthorizedObjectID authorizedObjectID = (AuthorizedObjectID) JDOHelper.getObjectId(authorizedObject);
AuthorizedObjectRef<Entity> authorizedObjectRef = entityUserSet.getAuthorizedObjectRef(authorizedObjectID);
this.authorizedObjects.put(authorizedObject, authorizedObjectRef != null ? Boolean.TRUE : Boolean.FALSE);
Map<Entity, Boolean> entityToAssigned = authorizedObjectIDToEntities.get(JDOHelper.getObjectId(authorizedObject));
if (entityToAssigned == null) {
entityToAssigned = new HashMap<Entity, Boolean>();
authorizedObjectIDToEntities.put((AuthorizedObjectID) JDOHelper.getObjectId(authorizedObject), entityToAssigned);
}
if (authorizedObjectRef != null) {
// collect all entities which are assigned to the AuthorisedObject
Collection<Entity> authorisedObjectEntities = new HashSet<Entity>();
for (EntityRef<Entity> entityRef : authorizedObjectRef.getEntityRefs()) {
authorisedObjectEntities.add(entityRef.getEntity());
}
// iterate through all Entities and fill map which are assigned an which not
for (Entity entity : entities) {
entityToAssigned.put(entity, authorisedObjectEntities.contains(entity));
}
}
else {
// iterate through all Entities and fill map which are assigned an which not
for (Entity entity : entities) {
entityToAssigned.put(entity, Boolean.FALSE);
}
}
}
}
else {
authorizedObjects.clear();
authorizedObjectIDToEntities.clear();
}
inheritedEntityUserSetResolver = null;
propertyChangeSupport.firePropertyChange(PROPERTY_NAME_ENTITY_USER_SET_LOADED, null, entityUserSet);
loaded = true;
} finally {
monitor.done();
}
}
protected String[] getEntityUserSetFetchGroups()
{
if (entityUserSetFetchGroups == null) {
Set<String> fgs = CollectionUtil.array2HashSet(FETCH_GROUPS_ENTITY_USER_SET);
fgs.addAll(CollectionUtil.array2HashSet(getEntityFetchGroups()));
entityUserSetFetchGroups = CollectionUtil.collection2TypedArray(fgs, String.class);
}
return entityUserSetFetchGroups;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName,
listener);
}
public void store(ProgressMonitor monitor)
{
checkLoaded();
// if (entityUserSet == null) {
// throw new IllegalStateException("entityUserSet is null, this should never happen!");
// }
monitor.beginTask(Messages.getString("org.nightlabs.jfire.entityuserset.ui.EntityUserSetPageControllerHelper.task.saveEntityUserSet"), 100); //$NON-NLS-1$
try {
if (entityUserSet != null) {
Collection<AuthorizedObjectID> oldEntityUserSetAuthorizedObjectIDs = new HashSet<AuthorizedObjectID>(
entityUserSet.getAuthorizedObjectRefs().size());
for (AuthorizedObjectRef<Entity> authorizedObjectRef : entityUserSet.getAuthorizedObjectRefs()) {
oldEntityUserSetAuthorizedObjectIDs.add(authorizedObjectRef.getAuthorizedObjectIDAsOID());
}
if (entityUserSet.getEntityUserSetController() == null) {
entityUserSet.setEntityUserSetController(new EntityUserSetControllerClientImpl());
}
// add or remove edited authorizedObjects
for (Map.Entry<AuthorizedObject, Boolean> entry : authorizedObjects.entrySet()) {
AuthorizedObject authorizedObject = entry.getKey();
Boolean assigned = entry.getValue();
AuthorizedObjectID authorizedObjectID = (AuthorizedObjectID) JDOHelper.getObjectId(authorizedObject);
if (assigned) {
// if the authorizedObject is not yet included do it.
if (!oldEntityUserSetAuthorizedObjectIDs.contains(authorizedObjectID)) {
entityUserSet.addAuthorizedObject(authorizedObjectID);
}
}
else {
// if the authorizedObject is still contained, remove it
if (oldEntityUserSetAuthorizedObjectIDs.contains(authorizedObjectID)) {
entityUserSet.removeAuthorizedObject(authorizedObjectID);
}
}
}
monitor.worked(10);
// add or remove edited entities per authorizedObject
for (AuthorizedObjectRef<Entity> authorizedObjectRef : entityUserSet.getAuthorizedObjectRefs()) {
AuthorizedObjectID authorizedObjectID = authorizedObjectRef.getAuthorizedObjectIDAsOID();
Map<Entity, Boolean> entityToAssignment = authorizedObjectIDToEntities.get(authorizedObjectID);
for (Map.Entry<Entity, Boolean> entry : entityToAssignment.entrySet()) {
Entity entity = entry.getKey();
Boolean value = entry.getValue();
boolean entityFound = false;
for (Iterator<EntityRef<Entity>> it = authorizedObjectRef.getEntityRefs().iterator(); it.hasNext(); ) {
EntityRef<Entity> entityRef = it.next();
Entity e = entityRef.getEntity();
if (e.equals(entity)) {
if (!value) {
authorizedObjectRef.removeEntity(entity);
}
entityFound = true;
break;
}
}
if (!entityFound && value) {
authorizedObjectRef.addEntity(entity);
}
}
}
monitor.worked(10);
entityUserSet = EntityUserSetDAO.sharedInstance().storeEntityUserSet(entityUserSet,
true, getEntityUserSetFetchGroups(), NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new SubProgressMonitor(monitor, 80));
}
} finally {
monitor.done();
}
}
public boolean isEntityUserSetInitiallyInherited() {
return getInheritedEntityUserSetResolver().isEntityUserSetInherited();
}
}