Jasig/person-directory — pull request #4 by dmccallum (2013-09-20 17:40:43+00:00)
Title: SSP-1668 Support case-insensitive query, result and data attrib values

Addresses SSP-1668 and PERSONDIR-74

In the uportal-user thread that prompted those two tickets I had
suggested a patch to {{BaseAdditiveAttributeMerger}} might do
the trick. Indeed it does work, sort of
(https://github.com/dmccallum/person-directory/tree/SSP-1668).
That patch is limited to username attributes and only addresses
*result* attribute case-sensitivity (as opposed to also supporting
case-insensitive *query* attributes, which is probably what one
expects if PD/uP were to claim to support case-insensitive
usernames/attributes). Also, because it only deals with
`IPersonAttributes#getName()`, you can end up with oddities
like that field's casing being canonicalized, but not the casing
of the actual attribute from which it was derived. This can lead
to a confusing user experience when browsing user attributes
in uPortal, for example. And the fact that this patch actually
changes attribute values was also a bit of a departure from the way
I think `IAttributeMerger` impls have worked in the past, where
they've mostly been responsible for choosing from among or
collecting many attribute values, not so much changing the actual
values returned from DAOs.

So I ended up taking a different approach and moved the case-
sensitivity "down" into the DAO layer, which is the approach
represented by this pull request. It also generalizes the solution to
support all result, query, and data attributes, plus special username
handling. SSP is currently running this patch, along with a supporting
uPortal patch
(https://github.com/Jasig/uPortal/commit/1ef731e27a1eae8e413aa3bcc97433931eb462c6)
in it's nightly build environment.

Sample `personDirectoryContext.xml` config from that patch:

A bean for listing all app-layer username attributes:
```xml

username
uid
username
user.login.id
schoolId

```

An abstract bean for any DAO that needs to canonicalize
`IPersonAttributes.getName()` values:

```xml

```

An abstract bean for a DAO that also canonicalizes username query
and result attributes:

```xml

```

Then `requestAttributesDao` extends `usernameCanonicalizing`.
`uPortalAccountUserSource` and `uPortalJdbcUserSource` extend
`logicalAttributeCanonicalizing`. `uPortalJdbcUserSource` also adds the
following to canonicalize in-database username values:

```xml

USER_NAME

```

This does seem to take care of both the search use case described in
SSP-1668 as well as uP-local logins using a non-canonical username
casing. But I'm a bit concerned it might not address all permutations of
the latter. In particular, I'm not convinced the portlet user attributes are
being properly canonicalized. But that's a uPortal issue, not a PD issue.

This is obviously a very large patch and I expect you may want to sit on
it for a while while it soaks a bit in the SSP bathwaters.

##### Following is just the standard copy/paste from the original commit log:

Also some special handling for username case-sensitivity, reflecting
the existing special treatment of that property throughout PD.

Username case-insensitivity was the primary motivation for this patch,
but the solution was much more general.

All attribute values are still case-sensitive by default, preserving
legacy behavior.

Configure case-insenstivity on query attributes if you want searches
to be case-insensitive. If your underlying data layer is case
sensitive and stores values in non-canonical casings, you'll also
need to set corresponding data attribute case-insensitivity config.
Not all data layers will handle this equally well, though. If the
data layer does not support function-based indices you'll want to
prefer storing data in a canonical casing.

Configure case-insensitivity in result attributes if you want to
normalize in-application representation of certain attributes. This
is most useful for usernames.

Splitting query and result configuration in this way allows for
case-insensitive attribute search while preserving data-layer
attribute value casing. E.g. you may want case-insensitive search
on givenName but you don't want all those values converted to
lower case when returned to the application. (Note that uPortal's
JPA DAO (which is actually outside the PD DAO hierarchy) already
supported this for non-username attributes.)

Query and result attribute case-sensitivity is configurable for
subclasses of AbstractQueryPersonAttributeDao.

Data attribute case-sensitivity is configurable for subclasses of
AbstractJdbcPersonAttributeDao. This patch did not include direct
support for LdapPersonAttributeDao because the LDAP schema typically
specifies which attributes should be handled case-insensitively, thus
the data layer effectively solves the problem for us, assuming a
well-designed schema.

All case-sensitivity config is in terms of application- rather than
data-layer attribute names. This allows for configuration to be
consolidated, e.g. into one or more abstract parent beans, because
the sensitivity policy can be set once per application attribute
rather than once for every uniquely named data-layer attribute. It
also more accurately reflects the intent of the configuration, which
is to declare the global case-sensitivity assumptions the application
makes.