package com.idega.user.business;
import java.rmi.RemoteException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.ejb.FinderException;
import com.idega.core.accesscontrol.data.ICPermission;
import com.idega.presentation.IWContext;
import com.idega.user.data.CachedGroup;
import com.idega.user.data.Group;
import com.idega.util.GenericGroupComparator;
/**
* Description: A comparator for all "sorts" of groups that implement GenericGroup. Mainly used to order groups by name and locale.<br>
* It can handle can handle comparing (groupA,groupB) and also (collectionOfGroupA,CollectionOfGroupB);
* Copyright: Copyright (c) 2003
* Company: Idega Software
* @author <a href="mailto:eiki@idega.is">Eirikur S. Hrafnsson</a>
* @version 1.0
*/
public class GroupComparator extends GenericGroupComparator{
private GroupBusiness groupBiz;
private boolean areICPermissions = false;
private boolean sortByParents = false;
private int topmostParentLevel = -1;
private static String CACHE_PARENTS_APPLICATION_ATTRIBUTE = "CACHE_PARENTS";
private static String CACHE_GROUPS_APPLICATION_ATTRIBUTE = "CACHE_GROUPS";
private Map applicationCachedGroups = null;
private Map applicationCachedParents = null;
private Map cachedGroups = new HashMap();
private Map cachedParentsRecursiveAndCurrentGroup = new HashMap();
public GroupComparator(IWContext iwc) {
super(iwc);
}
public int compare(Object groupAOrCollectionOfGroupA, Object groupBOrCollectionOfGroupB) {
if( this.areICPermissions){
return compareICPermissionCollections(groupAOrCollectionOfGroupA,groupBOrCollectionOfGroupB);
}
else if( groupAOrCollectionOfGroupA instanceof Collection ){
((Collection)groupAOrCollectionOfGroupA).iterator().next() ;
return super.compare(((Collection)groupAOrCollectionOfGroupA).iterator().next(),((Collection)groupBOrCollectionOfGroupB).iterator().next());
}
else if( groupAOrCollectionOfGroupA instanceof Group ){
return compareGroups(groupAOrCollectionOfGroupA, groupBOrCollectionOfGroupB);
}
else{
return super.compare(groupAOrCollectionOfGroupA,groupBOrCollectionOfGroupB);
}
}
/**
* Compares a collection of ICPermissions. It gets the group from GroupBusiness.getGroupByGroupId( ICPermission.getContextValue())
* @param groupAOrCollectionOfGroupA
* @param groupBOrCollectionOfGroupB
* @return
*/
private int compareICPermissionCollections(Object permissionCollectionA, Object permissionCollectionB) {
int comp = 0;
CachedGroup cachedGroupA = null;
CachedGroup cachedGroupB = null;
try {
this.applicationCachedGroups = (Map)this._iwc.getApplicationContext().getApplicationAttribute(CACHE_GROUPS_APPLICATION_ATTRIBUTE);
if(this.applicationCachedGroups == null){
this.applicationCachedGroups = new HashMap();
this._iwc.getApplicationContext().setApplicationAttribute(CACHE_GROUPS_APPLICATION_ATTRIBUTE, this.applicationCachedGroups);
}
cachedGroupA = checkForCachedGroups(permissionCollectionA);
cachedGroupB = checkForCachedGroups(permissionCollectionB);
if (this.sortByParents) {
this.applicationCachedParents= (Map)this._iwc.getApplicationContext().getApplicationAttribute(CACHE_PARENTS_APPLICATION_ATTRIBUTE);
if(this.applicationCachedParents == null){
this.applicationCachedParents = new HashMap();
this._iwc.getApplicationContext().setApplicationAttribute(CACHE_PARENTS_APPLICATION_ATTRIBUTE, this.applicationCachedParents);
}
Collection parentsA = getParentGroupsRecursive(cachedGroupA);
Collection parentsB = getParentGroupsRecursive(cachedGroupB);
comp = compareRecursive(parentsA, parentsB);
}
}
catch (NumberFormatException e) {
e.printStackTrace();
}
catch (RemoteException e) {
e.printStackTrace();
}
catch (FinderException e) {
e.printStackTrace();
}
if (comp == 0){
Collator collator = Collator.getInstance(this._iwc.getCurrentLocale());
comp = collator.compare(cachedGroupA.getName(), cachedGroupB.getName());
}
return comp;
}
/**
* Compares groups
* @param groupAOrCollectionOfGroupA
* @param groupBOrCollectionOfGroupB
* @return
*/
private int compareGroups(Object groupA, Object groupB) {
int comp = 0;
CachedGroup cachedGroupA = null;
CachedGroup cachedGroupB = null;
try {
this.applicationCachedGroups = (Map)this._iwc.getApplicationContext().getApplicationAttribute(CACHE_GROUPS_APPLICATION_ATTRIBUTE);
if(this.applicationCachedGroups == null){
this.applicationCachedGroups = new HashMap();
this._iwc.getApplicationContext().setApplicationAttribute(CACHE_GROUPS_APPLICATION_ATTRIBUTE, this.applicationCachedGroups);
}
cachedGroupA = new CachedGroup((Group)groupA);
cachedGroupB = new CachedGroup((Group)groupB);
String keyA = cachedGroupA.getPrimaryKey().toString();
String keyB = cachedGroupB.getPrimaryKey().toString();
if (this.applicationCachedGroups.containsKey(keyA)) {
this.applicationCachedGroups.put(keyA, cachedGroupA);
}
if (this.applicationCachedGroups.containsKey(keyB)) {
this.applicationCachedGroups.put(keyB, cachedGroupB);
}
if (this.sortByParents) {
this.applicationCachedParents= (Map)this._iwc.getApplicationContext().getApplicationAttribute(CACHE_PARENTS_APPLICATION_ATTRIBUTE);
if(this.applicationCachedParents == null){
this.applicationCachedParents = new HashMap();
this._iwc.getApplicationContext().setApplicationAttribute(CACHE_PARENTS_APPLICATION_ATTRIBUTE, this.applicationCachedParents);
}
Collection parentsA = getParentGroupsRecursive(cachedGroupA);
Collection parentsB = getParentGroupsRecursive(cachedGroupB);
comp = compareRecursive(parentsA, parentsB);
}
}
catch (NumberFormatException e) {
e.printStackTrace();
}
catch (RemoteException e) {
e.printStackTrace();
}
catch (FinderException e) {
e.printStackTrace();
}
if (comp == 0){
Collator collator = Collator.getInstance(this._iwc.getCurrentLocale());
comp = collator.compare(cachedGroupA.getName(), cachedGroupB.getName());
}
return comp;
}
/**
* @param cachedGroup
* @return
* @throws RemoteException
*/
private Collection getParentGroupsRecursive(CachedGroup cachedGroup) throws RemoteException, FinderException {
Collection parentGroupsRecursive = null;
if (this.cachedParentsRecursiveAndCurrentGroup!=null) {
String key = cachedGroup.getPrimaryKey().toString();
if (this.cachedParentsRecursiveAndCurrentGroup.containsKey(key)) {
parentGroupsRecursive = (Collection)this.cachedParentsRecursiveAndCurrentGroup.get(key);
}
else
{
parentGroupsRecursive = getParentsRecursiveAndCurrentGroup(cachedGroup);
this.cachedParentsRecursiveAndCurrentGroup.put(key, parentGroupsRecursive);
if (parentGroupsRecursive == null) {
setTopmostParentLevel(0);
}
else {
if (this.topmostParentLevel == -1 || this.topmostParentLevel > parentGroupsRecursive.size()) {
setTopmostParentLevel(parentGroupsRecursive.size());
}
}
}
}
else {
parentGroupsRecursive = getParentsRecursiveAndCurrentGroup(cachedGroup);
}
return parentGroupsRecursive;
}
/**
* @param cachedGroup
* @return
* @throws RemoteException
*/
private Collection getParentsRecursiveAndCurrentGroup(CachedGroup cachedGroup) throws RemoteException, FinderException {
Collection parentGroupsRecursive = getParentGroupsRecursive(cachedGroup.getPrimaryKey());
if (parentGroupsRecursive!=null) {
int collSize = parentGroupsRecursive.size();
List tempCollection = new ArrayList();
tempCollection.addAll(parentGroupsRecursive);
parentGroupsRecursive.clear();
for (int i = collSize-1; i >=0 ;i--) {
parentGroupsRecursive.add(tempCollection.get(i));
}
}
else {
parentGroupsRecursive = new ArrayList();
}
parentGroupsRecursive.add(cachedGroup);
return parentGroupsRecursive;
}
private Collection getParentGroupsRecursive(Integer groupId) throws RemoteException, FinderException {
Collection parentGroupsRecursive = new ArrayList();
getParentGroupsRecursive(parentGroupsRecursive, groupId);
return parentGroupsRecursive;
}
private void getParentGroupsRecursive(Collection parentsRecursive, Integer groupId) throws RemoteException, FinderException {
Group group = null;
Group parent = null;
if (this.applicationCachedParents.containsKey(groupId.toString())) {
Collection col = (Collection)this.applicationCachedParents.get(groupId.toString());
Iterator it = col.iterator();
Integer parentId = null;
CachedGroup cachedParentGroup = null;
if (it.hasNext()) {
parentId = (Integer)it.next();
String key = parentId.toString();
if (this.applicationCachedGroups.containsKey(key)) {
cachedParentGroup = (CachedGroup)this.applicationCachedGroups.get(key);
}
else if (this.cachedGroups.containsKey(key)) {
parent = (Group)this.cachedGroups.get(key);
cachedParentGroup = new CachedGroup(parent);
this.applicationCachedGroups.put(key, cachedParentGroup);
}
else {
parent = this.groupBiz.getGroupByGroupID(parentId.intValue());
cachedParentGroup = new CachedGroup(parent);
this.cachedGroups.put(key,parent);
this.applicationCachedGroups.put(key, cachedParentGroup);
}
parentsRecursive.add(cachedParentGroup);
getParentGroupsRecursive(parentsRecursive, cachedParentGroup.getPrimaryKey());
}
}
else {
String key = groupId.toString();
if (this.cachedGroups.containsKey(key)) {
group = (Group)this.cachedGroups.get(key);
CachedGroup cachedGroup = new CachedGroup(group);
this.applicationCachedGroups.put(key, cachedGroup);
}
else {
group = this.groupBiz.getGroupByGroupID(groupId.intValue());
CachedGroup cachedGroup = new CachedGroup(group);
this.cachedGroups.put(key, group);
this.applicationCachedGroups.put(key, cachedGroup);
}
Collection parents = group.getParentGroups(this.applicationCachedParents, this.cachedGroups);
Iterator parIt = parents.iterator();
if (parIt.hasNext()) {
parent = (Group)parIt.next();
if (parent!= null) {
CachedGroup cachedParentGroup = new CachedGroup(parent);
parentsRecursive.add(cachedParentGroup);
getParentGroupsRecursive(parentsRecursive, cachedParentGroup.getPrimaryKey());
}
}
}
}
/**
* @param comp
* @param cachedGroupA
* @param cachedGroupB
* @return
*/
private int compareGroupTypes(CachedGroup cachedGroupA, CachedGroup cachedGroupB) {
int comp = 0;
Collator collator = Collator.getInstance(this._iwc.getCurrentLocale());
String groupType1 = this._iwc.getIWMainApplication().getBundle(IW_BUNDLE_IDENTIFIER).getResourceBundle(this._iwc.getCurrentLocale()).getLocalizedString(cachedGroupA.getGroupType());
String groupType2 = this._iwc.getIWMainApplication().getBundle(IW_BUNDLE_IDENTIFIER).getResourceBundle(this._iwc.getCurrentLocale()).getLocalizedString(cachedGroupB.getGroupType());
if (groupType1 != null && groupType2 == null) {
comp = -1;
} else if (groupType1 == null && groupType2 != null) {
comp = 1;
} else if (groupType1 != null && groupType2 != null) {
comp = collator.compare(groupType1, groupType2);
}
return comp;
}
/**
* @param parentsA
* @param parentsB
*/
private int compareRecursive(Collection parentsA, Collection parentsB) {
int comp = 0;
if ((parentsA == null || parentsA.isEmpty()) && (parentsB != null && !parentsB.isEmpty())) {
comp = -1;
}
else if ((parentsA != null && !parentsA.isEmpty()) && (parentsB == null || parentsB.isEmpty())) {
comp = 1;
}
else if ((parentsA != null && !parentsA.isEmpty()) && (parentsB != null && !parentsB.isEmpty())){
CachedGroup cachedParentGroupA = null;
CachedGroup cachedParentGroupB = null;
Iterator parAIt = parentsA.iterator();
Iterator parBIt = parentsB.iterator();
while (comp == 0) {
if (parAIt.hasNext() && parBIt.hasNext()) {
cachedParentGroupA = (CachedGroup)parAIt.next();
cachedParentGroupB = (CachedGroup)parBIt.next();
comp = compareGroupTypes(cachedParentGroupA, cachedParentGroupB);
if (comp == 0){
Collator collator = Collator.getInstance(this._iwc.getCurrentLocale());
comp = collator.compare(cachedParentGroupA.getName(), cachedParentGroupB.getName());
}
}
else if (!parAIt.hasNext() && parBIt.hasNext()) {
comp = -1;
}
else if (parAIt.hasNext() && !parBIt.hasNext()) {
comp = 1;
}
else {
break;
}
}
}
return comp;
}
/**
* The compatator checks if the two groups being compared have already been loaded
* and then gets them from a HashMap instead of loading them from the database
* Optimization done by Sigtryggur 6.7.2004
* @param permissionCollection
* @return group
*/
private CachedGroup checkForCachedGroups(Object permissionCollection) throws FinderException, RemoteException {
CachedGroup cachedGroup = null;
Group group = null;
String groupId = ((ICPermission) ((Collection) permissionCollection).iterator().next()).getContextValue();
String key = groupId;
if (this.applicationCachedGroups.containsKey(key)) {
cachedGroup = (CachedGroup)this.applicationCachedGroups.get(key);
}
else if (this.cachedGroups.containsKey(key)) {
group = (Group)this.cachedGroups.get(groupId);
cachedGroup = new CachedGroup(group);
this.applicationCachedGroups.put(key, cachedGroup);
}
else
{
group = this.groupBiz.getGroupByGroupID(Integer.parseInt(groupId));
cachedGroup = new CachedGroup(group);
this.cachedGroups.put(key, group);
this.applicationCachedGroups.put(key, cachedGroup);
}
return cachedGroup;
}
public String getIndentedGroupName(CachedGroup cachedGroup) {
int indent = 0;
String indentString = "";
Object obj = getCachedParentsRecursiveAndCurrentGroup().get(cachedGroup.getPrimaryKey().toString());
if (obj != null) {
indent = ((Collection)obj).size();
}
indent = indent - getTopmostParentLevel();
for (int i=0;i<indent;i++) {
indentString = "· " + indentString;
}
indentString = indentString + cachedGroup.getName();
return indentString;
}
/**
* Tells the comparator to check inside the collections and get the group from the ICPermission bean.
* It is mandatory to set the GroupBusiness also if this is set to true.
* @param arePermission
*/
public void setObjectsAreICPermissions(boolean arePermission){
this.areICPermissions = arePermission;
}
/**
* Is mandatory only if setObjectsAreICPermissions(true).
*/
public void setGroupBusiness(GroupBusiness groupBiz){
this.groupBiz = groupBiz;
}
/**
* @param sortByParents The sortByParents to set.
*/
public void setSortByParents(boolean sortByParents) {
this.sortByParents = sortByParents;
}
public Map getApplicationCachedGroups() {
return this.applicationCachedGroups;
}
public Map getCachedParentsRecursiveAndCurrentGroup() {
return this.cachedParentsRecursiveAndCurrentGroup;
}
/**
* @return Returns the topmostParentLevel.
*/
public int getTopmostParentLevel() {
return this.topmostParentLevel;
}
/**
* @param topmostParentLevel The topmostParentLevel to set.
*/
public void setTopmostParentLevel(int topmostParentLevel) {
this.topmostParentLevel = topmostParentLevel;
}
}