I have to say, what you have there looks great, very easy to use and you understand
what's going on right away. I'm really not sure why we'd go to all the trouble
of creating a QL for this when we have what you've just added. I think this would be a
great place to get some user feedback over the next six months or so.
Sent from my iPhone
On Oct 30, 2012, at 17:02, Shane Bryzak <sbryzak(a)redhat.com> wrote:
I knew I shouldn't have clicked the "Send" button so
quickly. :) After 5 minutes of thinking about this, there would be no reason to deprecate
the Query API. JPA supports both a query language and a criteria API, so there's no
reason why we couldn't do both.
On 10/31/2012 08:52 AM, Shane Bryzak wrote:
> I've made some further minor changes to the Query API, specifically in the area
of memberships. By introducing a new QueryParameter implementation called
MembershipParameter, we are now able to support queries that look like this:
>
> List<User> users = this.<User>createQuery()
> .setParameter(User.MEMBER_OF.group("Head
Office").role("Admin"), true)
> .setParameter(User.MEMBER_OF.group("Springfield"), false)
> .setParameter(User.MEMBER_OF.role("Contractor"), false)
> .getResultList();
>
> Translation of the above code: return all users that have the "Admin" role
in the "Head Office" group, but aren't a member of the
"Springfield" group and don't have the application role
"Contractor".
>
> This support for membership exclusion gives us a little bit more flexibility in what
we can return from the IdentityQuery. I have to say though, I'm still not 100%
satisfied with the Query API - my opinion is that we should mark this feature as already
deprecated in the 3.0 release, and in 3.1 introduce a proper query language (PLQL -
PicketLink Query Language) where the developer is able to provide free-form queries, e.g.
being able to run something like "SELECT User WHERE MEMBER_OF(Group("Head
Office"), Role("Office Administrator")) and enabled = true and createdDate
< :createdDate and not in (SELECT User WHERE NOT MEMBER_OF("Admin"))".
>
> Maybe this feature would be going too far, so please let me know if you think it is.
>
>
> On 10/30/2012 08:41 PM, Shane Bryzak wrote:
>> I've managed to trim the IdentityQuery API down to just this:
>>
>> public interface IdentityQuery<T extends IdentityType> {
>> public enum Operator { equals, notEquals, greaterThan, lessThan };
>> IdentityQuery<T> setOffset(int offset);
>> IdentityQuery<T> setLimit(int limit);
>> IdentityQuery<T> setParameter(QueryParameter param, Object value);
>> IdentityQuery<T> setParameter(QueryParameter param, Operator operator,
Object value);
>> List<T> getResultList();
>> }
>>
>> While I did like the concept of Pedro's method refactor, I think that
sticking with an API that mimics that of JPA (which most developers should be already
familiar with) will be more intuitive.
>>
>> To get rid of the setAttribute() methods, I had to do a little bit of hackery by
adding this to the IdentityType interface:
>>
>> public class AttributeParameter implements QueryParameter {
>> private String name;
>> public AttributeParameter(String name) {
>> this.name = name;
>> }
>> public String getName() {
>> return name;
>> }
>> }
>> public final class PARAM_ATTRIBUTE {
>> public static AttributeParameter byName(String name) {
>> return new AttributeParameter(name);
>> }
>> }
>>
>> This then allows us to simply use the setParameter() method to set attribute
values also, like so:
>>
>> List<User> users = im.<User>createQuery()
>> .setParameter(User.PARAM_ENABLED, true)
>> .setParameter(User.PARAM_ATTRIBUTE.byName("foo"),
"bar")
>> .getResultList();
>>
>> I'm still trying to decide if I like this or not. I guess it somewhat
simplifies usage as the developer can follow the same pattern for setting all parameter
values. What do you guys think about it?
>>
>>
>> On 10/30/2012 01:49 PM, Jason Porter wrote:
>>> On Oct 29, 2012, at 21:31, Shane Bryzak <sbryzak(a)redhat.com> wrote:
>>>
>>>> On 10/30/2012 12:32 PM, Jason Porter wrote:
>>>>> On Oct 29, 2012, at 17:20, Shane Bryzak <sbryzak(a)redhat.com>
wrote:
>>>>>
>>>>>> On 10/30/2012 01:20 AM, Jason Porter wrote:
>>>>>>> I very much like the DSL you have going there. Removing the
Range class is also a good idea, imo. However, I'm at -1 for the use of enums. You
can't extend them, and you can't anticipate everything a user would add to a
class. Sure we could do it in the simple idm idea where we provide the structure, but as
soon as they advance past that then they're forced to use a different API.
>>>>>>
>>>>>> I agree, I wasn't a fan of using an enum either but at the
time I hashed this out I couldn't think of a better alternative. How about instead of
enums we introduce a marker interface like this:
>>>>>>
>>>>>> public interface QueryParameter {
>>>>>>
>>>>>> }
>>>>>>
>>>>>> Then we can simply define supported parameters directly on the
core identity model interfaces, as Pedro has suggested:
>>>>>>
>>>>>> public interface User extends IdentityType, Serializable {
>>>>>> public static final QueryParameter FIRST_NAME = new
QueryParameter() {};
>>>>>> public static final QueryParameter LAST_NAME = new
QueryParameter() {};
>>>>>> ...
>>>>>> }
>>>>>>
>>>>>> Then the method signature for
IdentityQuery.setParameter would look something like this:
>>>>>>
>>>>>> IdentityQuery<T> setParameter(QueryParameter param, Object
value);
>>>>>>
>>>>>> This then makes the parameter set extensible (anyone can create
their own) and we can create an SPI (or just make the IdentityStore implementations
extensible themselves) so that developers can provide support for their own custom query
parameters (not to mention it makes it more future proof if we want to add more parameter
types later).
>>>>>
>>>>> Any reason not to do a generic interface or abstract class?
QueryParam<TYPE> and have a void setValue(TYPE val), a <TYPE> getValue() and a
String getName() on that interface/class? That would cut down on an argument.
>>>>
>>>> I'm not quite getting this - could you give an example of what the
API would look like?
>>>
>>> I've thought about it a bit more and like your proposal better for the
enhanced readability.
>>>
>>>>>
>>>>> Though the final empty interfaces from the classes does read nicely.
>>>>>
>>>>>>>
>>>>>>> On Mon, Oct 29, 2012 at 7:10 AM, Pedro Igor Silva
<psilva(a)redhat.com> wrote:
>>>>>>>> I liked your proposal, it is simple and clear.
>>>>>>>>
>>>>>>>> Considering what you did I thought in another solution.
At first glance, it seems more odd. But I think it can be more intuitive for users. For
example, instead of having the Param.memberOf, users may use query.role(Role) or
query.group(Group) directly.
>>>>>>>>
>>>>>>>> IdentityManager identityManager = // get the
identity manager;
>>>>>>>>
>>>>>>>> Query<User> query =
identityManager.<User>createQuery();
>>>>>>>>
>>>>>>>> query
>>>>>>>> .limit(100)
>>>>>>>> .offset(1)
>>>>>>>> .where()
>>>>>>>> .id("1")
>>>>>>>>
>>>>>>>> .property(User.FIRST_NAME,
OPERATOR.equals, "John")
>>>>>>>> .property(User.EXPIRATION_DATE,
OPERATOR.lessThan, new Date())
>>>>>>>>
>>>>>>>> .attribute("ssn",
OPERATOR.equals, "SSN-123")
>>>>>>>>
>>>>>>>> .role(new SimpleRole("Payroll
Officer"))
>>>>>>>>
>>>>>>>> .group(new
SimpleGroup("Superuser", "Superuser", null));
>>>>>>>>
>>>>>>>> List<User> list = query.list();
>>>>>>>>
>>>>>>>> for (User user : list) {
>>>>>>>> // handle users
>>>>>>>> }
>>>>>>>>
>>>>>>>> I think we can avoid having a Range class/interface by
using some methods on the Query interface (eg. limit and offset above). Th Query interface
can be used only to configure how the query should be executed, global configuration,
etc.
>>>>>>>>
>>>>>>>> The Where interface can be useful to provide some
specific val
_______________________________________________
security-dev mailing list
security-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/security-dev