/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.coa.identity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.identity.KfsKimAttributes;
import org.kuali.rice.core.api.uif.RemotableAttributeError;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kim.api.role.RoleMembership;
import org.kuali.rice.kns.kim.role.RoleTypeServiceBase;
/**
* This role type service was designed to be attached to the KFS-SYS User role
*/
public class FinancialSystemUserRoleTypeServiceImpl extends RoleTypeServiceBase {
public static final String PERFORM_QUALIFIER_MATCH = "performQualifierMatch";
@Override
protected boolean performMatch(Map<String,String> qualification, Map<String,String> roleQualifier) {
// if we can not find the qualifier which tells us to perform the match, just return true
if (qualification == null || !Boolean.parseBoolean(qualification.get(PERFORM_QUALIFIER_MATCH))) {
return true;
}
// if chart and org aren't on the assignment we don't care, since we are only matching to get the default chart/org for a
// user in FinancialSystemUserServiceImpl
if (StringUtils.isBlank(roleQualifier.get(KfsKimAttributes.CHART_OF_ACCOUNTS_CODE)) || StringUtils.isBlank(roleQualifier.get(KfsKimAttributes.ORGANIZATION_CODE))) {
return false;
}
// exact match on namespace or qualifier namespace of kfs-sys works
if (StringUtils.equals(roleQualifier.get(KimConstants.AttributeConstants.NAMESPACE_CODE), qualification.get(KimConstants.AttributeConstants.NAMESPACE_CODE))
|| StringUtils.equals(KFSConstants.CoreModuleNamespaces.KFS, roleQualifier.get(KimConstants.AttributeConstants.NAMESPACE_CODE))) {
return true;
}
return false;
}
@Override
public List<RoleMembership> getMatchingRoleMemberships(Map<String,String> qualification, List<RoleMembership> roleMemberList) {
Map<String,String> translatedQualification = translateInputAttributes(qualification);
validateRequiredAttributesAgainstReceived(translatedQualification);
// if we can not find the qualifier which tells us to perform the match, just return all rows
if (translatedQualification == null || translatedQualification.isEmpty() || !Boolean.parseBoolean(translatedQualification.get(PERFORM_QUALIFIER_MATCH))) {
return roleMemberList;
}
// perform special matching to make a match that includes the namespace take priority
RoleMembership namespaceMatch = null;
RoleMembership nonNamespaceMatch = null;
// look for match
for (RoleMembership rmi : roleMemberList) {
// if chart and org aren't on the assignment we don't care, since we are only matching to get the default chart/org for
// a user in FinancialSystemUserServiceImpl
if (!(StringUtils.isBlank(rmi.getQualifier().get(KfsKimAttributes.CHART_OF_ACCOUNTS_CODE)) || StringUtils.isBlank(rmi.getQualifier().get(KfsKimAttributes.ORGANIZATION_CODE)))) {
if (StringUtils.equals(translatedQualification.get(KimConstants.AttributeConstants.NAMESPACE_CODE), rmi.getQualifier().get(KimConstants.AttributeConstants.NAMESPACE_CODE))) {
namespaceMatch = rmi;
}
else if (StringUtils.equals(KFSConstants.ParameterNamespaces.KFS, rmi.getQualifier().get(KimConstants.AttributeConstants.NAMESPACE_CODE))) {
nonNamespaceMatch = rmi;
}
}
}
List<RoleMembership> matchingMemberships = new ArrayList<RoleMembership>(1);
if (nonNamespaceMatch != null || namespaceMatch != null) {
matchingMemberships.add((namespaceMatch != null) ? namespaceMatch : nonNamespaceMatch);
}
return matchingMemberships;
}
/**
* note: for validating KFS-SYS User membership
* - if chart or org are specified, chart, org, and namespace are all required
* - none are required if not
* - can only have one assignment to the role for a given namespace - including no namespace
*
* @see org.kuali.rice.kim.service.support.impl.KimTypeInfoServiceBase#validateAttributes(org.kuali.rice.kim.bo.types.dto.AttributeSet)
*/
@Override
public List<RemotableAttributeError> validateAttributes(String kimTypeId, Map<String,String> attributes) {
List<RemotableAttributeError> errorList = new ArrayList <RemotableAttributeError>();
errorList.addAll(super.validateAttributes(kimTypeId, attributes));
String chartCode = attributes.get(KfsKimAttributes.CHART_OF_ACCOUNTS_CODE);
String organizationCode = attributes.get(KfsKimAttributes.ORGANIZATION_CODE);
String namespaceCode = attributes.get(KimConstants.AttributeConstants.NAMESPACE_CODE);
if(StringUtils.isBlank(chartCode) && StringUtils.isBlank(organizationCode)){
//remove chartofAccountCode, organizationCode and namespaceCode errors
//Object results = GlobalVariables.getMessageMap().getErrorMessagesForProperty(attributeName);
//RiceKeyConstants.ERROR_REQUIRED
removeError(KfsKimAttributes.CHART_OF_ACCOUNTS_CODE, errorList );
removeError(KfsKimAttributes.ORGANIZATION_CODE, errorList );
if(StringUtils.isBlank(namespaceCode)) {
removeError(KimConstants.AttributeConstants.NAMESPACE_CODE, errorList );
}
} //- if chart or org are specified, chart, org, and namespace are all required
//- none are required if not
else if (StringUtils.isNotEmpty(chartCode) || StringUtils.isNotEmpty(organizationCode)){
if(StringUtils.isBlank(chartCode) || StringUtils.isBlank(organizationCode) || StringUtils.isBlank(namespaceCode)) {
errorList.add(RemotableAttributeError.Builder.create(KimConstants.AttributeConstants.NAMESPACE_CODE, KFSKeyConstants.ERROR_CHART_OR_ORG_NOTEMPTY_ALL_REQUIRED).build());
}
}
return errorList;
}
protected void removeError( String attributeName, Collection<RemotableAttributeError> errorList ) {
Iterator<RemotableAttributeError> iter = errorList.iterator();
while ( iter.hasNext() ) {
if ( StringUtils.equals( iter.next().getAttributeName(), attributeName ) ) {
iter.remove();
}
}
}
@Override
public List<RemotableAttributeError> validateUniqueAttributes(String kimTypeId, Map<String,String> newAttributes, Map<String,String> oldAttributes){
if(areAllAttributeValuesEmpty(newAttributes)){
return Collections.emptyList();
} else
return super.validateUniqueAttributes(kimTypeId, newAttributes, oldAttributes);
}
protected boolean areAllAttributeValuesEmpty( Map<String,String> attributes){
boolean areAllAttributesEmpty = true;
if(attributes!=null)
for(String attributeNameKey: attributes.keySet()){
if(StringUtils.isNotBlank(attributes.get(attributeNameKey))){
areAllAttributesEmpty = false;
break;
}
}
return areAllAttributesEmpty;
}
@Override
public List<String> getUniqueAttributes(String kimTypeId){
return Collections.singletonList(KimConstants.AttributeConstants.NAMESPACE_CODE);
}
}