<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>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.&nbsp;<br><br>Sent from my iPhone</div><div><br>On Oct 30, 2012, at 17:02, Shane Bryzak &lt;<a href="mailto:sbryzak@redhat.com">sbryzak@redhat.com</a>&gt; wrote:<br><br></div><div><span></span></div><blockquote type="cite"><div>
  
    <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
  
  
    <div class="moz-cite-prefix">I knew I shouldn't have clicked the
      "Send" button so quickly. :)&nbsp; After 5 minutes of thinking about
      this, there would be no reason to deprecate the Query API.&nbsp; JPA
      supports both a query language and a criteria API, so there's no
      reason why we couldn't do both.&nbsp; <br>
      <br>
      On 10/31/2012 08:52 AM, Shane Bryzak wrote:<br>
    </div>
    <blockquote cite="mid:50905A42.6050901@redhat.com" type="cite">
      <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
      <div class="moz-cite-prefix">I've made some further minor changes
        to the Query API, specifically in the area of memberships.&nbsp; By
        introducing a new QueryParameter implementation called
        MembershipParameter, we are now able to support queries that
        look like this:<br>
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;User&gt; users = this.&lt;User&gt;createQuery()<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .setParameter(User.MEMBER_OF.group("Head
        Office").role("Admin"), true)<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        .setParameter(User.MEMBER_OF.group("Springfield"), false)<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .setParameter(User.MEMBER_OF.role("Contractor"),
        false)<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getResultList();<br>
        <br>
        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".&nbsp; <br>
        <br>
        This support for membership exclusion gives us a little bit more
        flexibility in what we can return from the IdentityQuery.&nbsp; 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 &lt; :createdDate and not in (SELECT User WHERE NOT
        MEMBER_OF("Admin"))".&nbsp; <br>
        <br>
        Maybe this feature would be going too far, so please let me know
        if you think it is.<br>
        <br>
        <br>
        On 10/30/2012 08:41 PM, Shane Bryzak wrote:<br>
      </div>
      <blockquote cite="mid:508FAEE4.3050202@redhat.com" type="cite">
        <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
        <div class="moz-cite-prefix">I've managed to trim the
          IdentityQuery API down to just this:<br>
          <br>
          public interface IdentityQuery&lt;T extends IdentityType&gt; {<br>
          &nbsp;&nbsp;&nbsp; public enum Operator { equals, notEquals, greaterThan,
          lessThan };<br>
          &nbsp;&nbsp;&nbsp; IdentityQuery&lt;T&gt; setOffset(int offset);<br>
          &nbsp;&nbsp;&nbsp; IdentityQuery&lt;T&gt; setLimit(int limit);<br>
          &nbsp;&nbsp;&nbsp; IdentityQuery&lt;T&gt; setParameter(QueryParameter param,
          Object value);<br>
          &nbsp;&nbsp;&nbsp; IdentityQuery&lt;T&gt; setParameter(QueryParameter param,
          Operator operator, Object value);<br>
          &nbsp;&nbsp;&nbsp; List&lt;T&gt; getResultList();<br>
          }<br>
          <br>
          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.<br>
          <br>
          To get rid of the setAttribute() methods, I had to do a little
          bit of hackery by adding this to the IdentityType interface:<br>
          <br>
          &nbsp;&nbsp;&nbsp; public class AttributeParameter implements QueryParameter
          {<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String name;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public AttributeParameter(String name) {<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name = name;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getName() {<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return name;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          &nbsp;&nbsp;&nbsp; }<br>
          &nbsp;&nbsp;&nbsp; public final class PARAM_ATTRIBUTE {<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static AttributeParameter byName(String name) {<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new AttributeParameter(name);<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
          &nbsp;&nbsp;&nbsp; }<br>
          <br>
          This then allows us to simply use the setParameter() method to
          set attribute values also, like so:<br>
          <br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;User&gt; users = im.&lt;User&gt;createQuery()<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .setParameter(User.PARAM_ENABLED, true)<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
          .setParameter(User.PARAM_ATTRIBUTE.byName("foo"), "bar")<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getResultList();<br>
          <br>
          I'm still trying to decide if I like this or not.&nbsp; I guess it
          somewhat simplifies usage as the developer can follow the same
          pattern for setting all parameter values.&nbsp; What do you guys
          think about it?<br>
          <br>
          <br>
          On 10/30/2012 01:49 PM, Jason Porter wrote:<br>
        </div>
        <blockquote cite="mid:61BF871B-C98B-4D3A-83E5-5DCD2EFD07EC@gmail.com" type="cite">
          <meta http-equiv="content-type" content="text/html;
            charset=ISO-8859-1">
          <div>On Oct 29, 2012, at 21:31, Shane Bryzak &lt;<a moz-do-not-send="true" href="mailto:sbryzak@redhat.com">sbryzak@redhat.com</a>&gt;


            wrote:</div>
          <div><br>
          </div>
          <blockquote type="cite">
            <div>
              <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
              <div class="moz-cite-prefix">On 10/30/2012 12:32 PM, Jason
                Porter wrote:<br>
              </div>
              <blockquote cite="mid:342B0DF8-E14E-4440-9863-F16670BD6FCE@gmail.com" type="cite">
                <meta http-equiv="content-type" content="text/html;
                  charset=ISO-8859-1">
                <div>On Oct 29, 2012, at 17:20, Shane Bryzak &lt;<a moz-do-not-send="true" href="mailto:sbryzak@redhat.com">sbryzak@redhat.com</a>&gt;



                  wrote:</div>
                <div><br>
                </div>
                <blockquote type="cite">
                  <div>
                    <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
                    <div class="moz-cite-prefix">On 10/30/2012 01:20 AM,
                      Jason Porter wrote:<br>
                    </div>
                    <blockquote cite="mid:CAF9TksM6DKBaAsqr+HannN-vHptPCUFN4m-_=8MNCeOW6_CLwg@mail.gmail.com" type="cite">I very much like the DSL you have
                      going there. Removing the Range class is also a
                      good idea, imo. &nbsp;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.<br>
                    </blockquote>
                    <br>
                    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.&nbsp; How about instead of enums we
                    introduce a marker interface like this:<br>
                    <br>
                    public interface QueryParameter {<br>
                    <br>
                    }<br>
                    <br>
                    Then we can simply define supported parameters
                    directly on the core identity model interfaces, as
                    Pedro has suggested:<br>
                    <br>
                    public interface User extends IdentityType,
                    Serializable {<br>
                    &nbsp;&nbsp;&nbsp; public static final QueryParameter FIRST_NAME =
                    new QueryParameter() {};<br>
                    &nbsp;&nbsp;&nbsp; public static final QueryParameter LAST_NAME =
                    new QueryParameter() {};<br>
                    &nbsp;&nbsp;&nbsp; ...<br>
                    }<br>
                    <br>
                    Then the method signature for
                    IdentityQuery.setParameter would look something like
                    this:<br>
                    <br>
                    IdentityQuery&lt;T&gt; setParameter(QueryParameter
                    param, Object value);<br>
                    <br>
                    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).<br>
                  </div>
                </blockquote>
                <div><br>
                </div>
                <div>Any reason not to do a generic interface or
                  abstract class? QueryParam&lt;TYPE&gt; and have a void
                  setValue(TYPE val), a &lt;TYPE&gt; getValue() and a
                  String getName() on that interface/class? That would
                  cut down on an argument. <br>
                </div>
              </blockquote>
              <br>
              I'm not quite getting this - could you give an example of
              what the API would look like?<br>
            </div>
          </blockquote>
          <div><br>
          </div>
          <div>I've thought about it a bit more and like your proposal
            better for the enhanced readability.&nbsp;</div>
          <br>
          <blockquote type="cite">
            <div>
              <blockquote cite="mid:342B0DF8-E14E-4440-9863-F16670BD6FCE@gmail.com" type="cite">
                <div><br>
                </div>
                <div>Though the final empty interfaces from the classes
                  does read nicely.&nbsp;</div>
                <br>
                <blockquote type="cite">
                  <div>
                    <blockquote cite="mid:CAF9TksM6DKBaAsqr+HannN-vHptPCUFN4m-_=8MNCeOW6_CLwg@mail.gmail.com" type="cite"><br>
                      <div class="gmail_quote">On Mon, Oct 29, 2012 at
                        7:10 AM, Pedro Igor Silva <span dir="ltr">&lt;<a moz-do-not-send="true" href="mailto:psilva@redhat.com" target="_blank">psilva@redhat.com</a>&gt;</span>
                        wrote:<br>
                        <blockquote class="gmail_quote" style="margin:0
                          0 0 .8ex;border-left:1px #ccc
                          solid;padding-left:1ex"> I liked your
                          proposal, it is simple and clear.<br>
                          <br>
                          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.<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; IdentityManager identityManager = //
                          get the identity manager;<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; Query&lt;User&gt; query =
                          identityManager.&lt;User&gt;createQuery();<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; query<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .limit(100)<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .offset(1)<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .where()<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .id("1")<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .property(User.FIRST_NAME,
                          OPERATOR.equals, "John")<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
                          .property(User.EXPIRATION_DATE,
                          OPERATOR.lessThan, new Date())<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .attribute("ssn",
                          OPERATOR.equals, "SSN-123")<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .role(new SimpleRole("Payroll
                          Officer"))<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .group(new
                          SimpleGroup("Superuser", "Superuser", null));<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; List&lt;User&gt; list = query.list();<br>
                          <br>
                          &nbsp; &nbsp; &nbsp; &nbsp; for (User user : list) {<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // handle users<br>
                          &nbsp; &nbsp; &nbsp; &nbsp; }<br>
                          <br>
                          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.<br>
                          <br>
                          The Where interface can be useful to provide
                          some specific val</blockquote></div></blockquote></div></blockquote></blockquote></div></blockquote></blockquote></blockquote></blockquote></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>security-dev mailing list</span><br><span><a href="mailto:security-dev@lists.jboss.org">security-dev@lists.jboss.org</a></span><br><span><a href="https://lists.jboss.org/mailman/listinfo/security-dev">https://lists.jboss.org/mailman/listinfo/security-dev</a></span><br></div></blockquote></body></html>