Package org.jasig.portal.persondir

Source Code of org.jasig.portal.persondir.LocalAccountPersonAttributeDao

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.jasig.portal.persondir;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AbstractDefaultAttributePersonAttributeDao;
import org.jasig.services.persondir.support.AttributeNamedPersonImpl;
import org.jasig.services.persondir.support.IUsernameAttributeProvider;
import org.jasig.services.persondir.support.MultivaluedPersonAttributeUtils;
import org.jasig.services.persondir.support.NamedPersonImpl;

/**
* LocalAccountPersonAttributeDao provides a person directory implementation
* that uses uPortal's internal account store.  This implementation overrides
* several methods of AbstractQueryPersonAttributeDao to allow for the use of
* arbitrary user attributes without requiring an administrator to add new
* entries to the result or query attribute mappings.
*
* @author Jen Bourey, jbourey@unicon.net
* @version $Revision$
*/
public class LocalAccountPersonAttributeDao extends AbstractDefaultAttributePersonAttributeDao {

    private ILocalAccountDao localAccountDao;
    private Map<String, Set<String>> resultAttributeMapping;
    private Set<String> possibleUserAttributes;
    private String unmappedUsernameAttribute = null;
    private String displayNameAttribute = "displayName";
    private Map<String, Set<String>> queryAttributeMapping;
   

    /**
     * Set the local portal account DAO.
     *
     * @param localAccountDao
     */
    public void setLocalAccountDao(ILocalAccountDao localAccountDao) {
        this.localAccountDao = localAccountDao;
    }

    public void setQueryAttributeMapping(final Map<String, ?> queryAttributeMapping) {
        final Map<String, Set<String>> parsedQueryAttributeMapping = MultivaluedPersonAttributeUtils.parseAttributeToAttributeMapping(queryAttributeMapping);
       
        if (parsedQueryAttributeMapping.containsKey("")) {
            throw new IllegalArgumentException("The map from attribute names to attributes must not have any empty keys.");
        }
       
        this.queryAttributeMapping = parsedQueryAttributeMapping;
    }
   
    /**
     * @return the resultAttributeMapping
     */
    public Map<String, Set<String>> getResultAttributeMapping() {
        return resultAttributeMapping;
    }
    /**
     * Set the {@link Map} to use for mapping from a data layer name to an attribute name or {@link Set} of attribute
     * names. Data layer names that are specified but have null mappings will use the column name for the attribute
     * name. Data layer names that are not specified as keys in this {@link Map} will be ignored.
     * <br>
     * The passed {@link Map} must have keys of type {@link String} and values of type {@link String} or a {@link Set}
     * of {@link String}.
     *
     * @param resultAttributeMapping {@link Map} from column names to attribute names, may not be null.
     * @throws IllegalArgumentException If the {@link Map} doesn't follow the rules stated above.
     * @see MultivaluedPersonAttributeUtils#parseAttributeToAttributeMapping(Map)
     */
    public void setResultAttributeMapping(Map<String, ?> resultAttributeMapping) {
        final Map<String, Set<String>> parsedResultAttributeMapping = MultivaluedPersonAttributeUtils.parseAttributeToAttributeMapping(resultAttributeMapping);
       
        if (parsedResultAttributeMapping.containsKey("")) {
            throw new IllegalArgumentException("The map from attribute names to attributes must not have any empty keys.");
        }
       
        final Collection<String> userAttributes = MultivaluedPersonAttributeUtils.flattenCollection(parsedResultAttributeMapping.values());
       
        this.resultAttributeMapping = parsedResultAttributeMapping;
        this.possibleUserAttributes = Collections.unmodifiableSet(new LinkedHashSet<String>(userAttributes));
    }
   
    /**
     * @return the userNameAttribute
     */
    public String getUnmappedUsernameAttribute() {
        return unmappedUsernameAttribute;
    }
    /**
     * The returned attribute to use as the userName for the mapped IPersons. If null the {@link #setDefaultAttributeName(String)}
     * value will be used and if that is null the {@link AttributeNamedPersonImpl#DEFAULT_USER_NAME_ATTRIBUTE} value is
     * used.
     *
     * @param userNameAttribute the userNameAttribute to set
     */
    public void setUnmappedUsernameAttribute(String userNameAttribute) {
        this.unmappedUsernameAttribute = userNameAttribute;
    }

    /**
     * Return the list of all possible attribute names.  This implementation
     * queries the database to provide a list of all mapped attribute names,
     * plus all attribute keys currently in-use in the database.
     *
     * @return Set
     */
    public Set<String> getPossibleUserAttributeNames() {
        final Set<String> names = new HashSet<String>();
        names.addAll(this.possibleUserAttributes);
        names.addAll(localAccountDao.getCurrentAttributeNames());
        names.add(displayNameAttribute);
        return names;
    }

    /**
     * Return the list of all possible query attributes.  This implementation
     * queries the database to provide a list of all mapped query attribute names,
     * plus all attribute keys currently in-use in the database.
     *
     * @return Set
     */
    public Set<String> getAvailableQueryAttributes() {
        if (this.queryAttributeMapping == null) {
            return Collections.emptySet();
        }
       
        return Collections.unmodifiableSet(this.queryAttributeMapping.keySet());
    }   
   
    /* (non-Javadoc)
     * @see org.jasig.services.persondir.IPersonAttributeDao#getPeopleWithMultivaluedAttributes(java.util.Map)
     */
    public final Set<IPersonAttributes> getPeopleWithMultivaluedAttributes(Map<String, List<Object>> query) {
        Validate.notNull(query, "query may not be null.");
       
        //Generate the query to pass to the subclass
        final LocalAccountQuery queryBuilder = this.generateQuery(query);
        if (queryBuilder == null) {
            this.logger.debug("No queryBuilder was generated for query " + query + ", null will be returned");
           
            return null;
        }
       
        //Get the username from the query, if specified
        final IUsernameAttributeProvider usernameAttributeProvider = this.getUsernameAttributeProvider();
       
        //Execute the query in the subclass
        final List<ILocalAccountPerson> unmappedPeople = localAccountDao.getPeople(queryBuilder);
        if (unmappedPeople == null) {
            return null;
        }

        //Map the attributes of the found people according to resultAttributeMapping if it is set
        final Set<IPersonAttributes> mappedPeople = new LinkedHashSet<IPersonAttributes>();
        for (final ILocalAccountPerson unmappedPerson : unmappedPeople) {
            final IPersonAttributes mappedPerson = this.mapPersonAttributes(unmappedPerson);
            mappedPeople.add(mappedPerson);
        }
       
        return Collections.unmodifiableSet(mappedPeople);
    }

    protected LocalAccountQuery generateQuery(Map<String, List<Object>> query) {
        LocalAccountQuery queryBuilder = new LocalAccountQuery();

        String userNameAttribute = this.getConfiguredUserNameAttribute();

        for (final Map.Entry<String, List<Object>> queryEntry : query.entrySet()) {
           
            String attrName = queryEntry.getKey();           
           
            if (userNameAttribute.equals(attrName)) {
                String value = queryEntry.getValue().get(0).toString();
                queryBuilder.setUserName(value);
            } else {
                List<String> values = new ArrayList<String>();
                for (Object o : queryEntry.getValue()) {
                    values.add(o.toString());
                }
                queryBuilder.setAttribute(attrName, values);
            }
           
        }
       
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Generated query builder '" + queryBuilder + "' from query Map " + query + ".");
        }
       
        return queryBuilder;
    }

    /**
     * This implementation uses the result attribute mapping to supplement, rather
     * than replace, the attributes returned from the database.
     */
    protected IPersonAttributes mapPersonAttributes(final ILocalAccountPerson person) {

        final Map<String, List<Object>> mappedAttributes = new LinkedHashMap<String, List<Object>>();
        mappedAttributes.putAll(person.getAttributes());

        // map the user's username to the portal's username attribute in the
        // attribute map
        mappedAttributes.put(this.getUsernameAttributeProvider().getUsernameAttribute(), Collections
                .<Object> singletonList(person.getName()));
       
        // if the user does not have a display name attribute set, attempt
        // to build one from the first and last name attributes
        if (!mappedAttributes.containsKey(displayNameAttribute) || mappedAttributes.get(displayNameAttribute).size() == 0 || StringUtils.isBlank((String) mappedAttributes.get(displayNameAttribute).get(0))) {
            final List<Object> firstNames = mappedAttributes.get("givenName");
            final List<Object> lastNames = mappedAttributes.get("sn");
            final StringBuilder displayName = new StringBuilder();
            if (firstNames != null && firstNames.size() > 0) {
                displayName.append(firstNames.get(0)).append(" ");
            }
            if (lastNames != null && lastNames.size() > 0) {
                displayName.append(lastNames.get(0));
            }
            mappedAttributes.put(displayNameAttribute, Collections.<Object>singletonList(displayName.toString()));
        }

        for (final Map.Entry<String, Set<String>> resultAttrEntry : this.getResultAttributeMapping().entrySet()) {
            final String dataKey = resultAttrEntry.getKey();
           
            //Only map found data attributes
            if (mappedAttributes.containsKey(dataKey)) {
                Set<String> resultKeys = resultAttrEntry.getValue();
               
                //If dataKey has no mapped resultKeys just use the dataKey
                if (resultKeys == null) {
                    resultKeys = Collections.singleton(dataKey);
                }
               
                //Add the value to the mapped attributes for each mapped key
                final List<Object> value = mappedAttributes.get(dataKey);
                for (final String resultKey : resultKeys) {
                    if (resultKey == null) {
                        //TODO is this possible?
                        if (!mappedAttributes.containsKey(dataKey)) {
                            mappedAttributes.put(dataKey, value);
                        }
                    }
                    else if (!mappedAttributes.containsKey(resultKey)) {
                        mappedAttributes.put(resultKey, value);
                    }
                }
            }
        }
       
        final IPersonAttributes newPerson;
       
        final String name = person.getName();
        if (name != null) {
            newPerson = new NamedPersonImpl(name, mappedAttributes);
        }
        else {
            final String userNameAttribute = this.getConfiguredUserNameAttribute();
            newPerson = new AttributeNamedPersonImpl(userNameAttribute, mappedAttributes);
        }
       
        return newPerson;
    }

    /**
     * @return The appropriate attribute to user for the user name. Since {@link #getDefaultAttributeName()} should
     * never return null this method should never return null either.
     */
    protected String getConfiguredUserNameAttribute() {
        //If configured explicitly use it
        if (this.unmappedUsernameAttribute != null) {
            return this.unmappedUsernameAttribute;
        }
       
        final IUsernameAttributeProvider usernameAttributeProvider = this.getUsernameAttributeProvider();
        return usernameAttributeProvider.getUsernameAttribute();
    }
   
}
TOP

Related Classes of org.jasig.portal.persondir.LocalAccountPersonAttributeDao

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.