/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.portlets.swapper;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.Validate;
import org.jasig.services.persondir.IPersonAttributeDao;
import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AbstractFlatteningPersonAttributeDao;
import org.jasig.services.persondir.support.MultivaluedPersonAttributeUtils;
import org.jasig.services.persondir.support.NamedPersonImpl;
import org.jasig.services.persondir.support.merger.IAttributeMerger;
import org.jasig.services.persondir.support.merger.ReplacingAttributeAdder;
import org.springframework.beans.factory.annotation.Required;
/**
* Provides for overriding certain attributes for certain users. By default uses a concurrent hash
* map to store the attributes
*
*/
public class OverwritingPersonAttributeDao extends AbstractFlatteningPersonAttributeDao {
private final IAttributeMerger attributeMerger = new ReplacingAttributeAdder();
private Map<String, Map<String, List<Object>>> attributeOverridesMap =
new ConcurrentHashMap<String, Map<String, List<Object>>>();
private IPersonAttributeDao delegatePersonAttributeDao;
/** @return the delegatePersonAttributeDao */
public IPersonAttributeDao getDelegatePersonAttributeDao() {
return delegatePersonAttributeDao;
}
/** @param delegatePersonAttributeDao the delegatePersonAttributeDao to set */
@Required
public void setDelegatePersonAttributeDao(IPersonAttributeDao delegatePersonAttributeDao) {
Validate.notNull(delegatePersonAttributeDao, "delegatePersonAttributeDao can not be null");
this.delegatePersonAttributeDao = delegatePersonAttributeDao;
}
/** @return the attributeOverridesMap */
public Map<String, Map<String, List<Object>>> getAttributeOverridesMap() {
return attributeOverridesMap;
}
/** @param attributeOverridesMap the attributeOverridesMap to set */
public void setAttributeOverridesMap(
Map<String, Map<String, List<Object>>> attributeOverridesMap) {
Validate.notNull(attributeOverridesMap, "attributeOverridesMap can not be null");
this.attributeOverridesMap = attributeOverridesMap;
}
public void setUserAttributeOverride(String uid, Map<String, Object> attributes) {
//Not really a seed but the function still works
final Map<String, List<Object>> multivaluedAttributes =
MultivaluedPersonAttributeUtils.toMultivaluedMap(attributes);
//Update the overrides map
this.attributeOverridesMap.put(uid, multivaluedAttributes);
}
public void removeUserAttributeOverride(String uid) {
//Remove the uid from the overrides map
this.attributeOverridesMap.remove(uid);
}
/* (non-Javadoc)
* @see org.jasig.services.persondir.IPersonAttributeDao#getPerson(java.lang.String)
*/
public IPersonAttributes getPerson(String uid) {
final IPersonAttributes person = this.delegatePersonAttributeDao.getPerson(uid);
if (person == null) {
return person;
}
return this.getOverriddenPerson(person);
}
/* (non-Javadoc)
* @see org.jasig.services.persondir.IPersonAttributeDao#getPeopleWithMultivaluedAttributes(java.util.Map)
*/
public Set<IPersonAttributes> getPeopleWithMultivaluedAttributes(
Map<String, List<Object>> query) {
final Set<IPersonAttributes> people =
this.delegatePersonAttributeDao.getPeopleWithMultivaluedAttributes(query);
if (people == null) {
return null;
}
final Set<IPersonAttributes> modifiedPeople = new LinkedHashSet<IPersonAttributes>();
for (final IPersonAttributes person : people) {
final IPersonAttributes mergedPerson = this.getOverriddenPerson(person);
modifiedPeople.add(mergedPerson);
}
return modifiedPeople;
}
/* (non-Javadoc)
* @see org.jasig.services.persondir.IPersonAttributeDao#getPossibleUserAttributeNames()
*/
public Set<String> getPossibleUserAttributeNames() {
return this.delegatePersonAttributeDao.getPossibleUserAttributeNames();
}
/* (non-Javadoc)
* @see org.jasig.services.persondir.IPersonAttributeDao#getAvailableQueryAttributes()
*/
public Set<String> getAvailableQueryAttributes() {
return this.delegatePersonAttributeDao.getAvailableQueryAttributes();
}
/** Gets the overridden version of the IPersonAttributes if attribute overrides exist */
protected IPersonAttributes getOverriddenPerson(final IPersonAttributes person) {
final String name = person.getName();
if (name == null) {
this.logger.info(
"IPerson '" + person + "' has no name and cannot have attributes overriden");
return person;
}
final Map<String, List<Object>> attributeOverrides = this.attributeOverridesMap.get(name);
if (attributeOverrides == null) {
return person;
}
final Map<String, List<Object>> personAttributes = person.getAttributes();
final Map<String, List<Object>> mutablePersonAttributes =
new LinkedHashMap<String, List<Object>>(personAttributes);
final Map<String, List<Object>> mergedAttributes =
this.attributeMerger.mergeAttributes(mutablePersonAttributes, attributeOverrides);
return new NamedPersonImpl(name, mergedAttributes);
}
}