<?xml version="1.0" encoding="UTF-8" ?>
    <prefix>
      <prefix>membership</prefix>
      <describeURL>/direct/membership/describe</describeURL>
      <summary>Represents a user's membership in a location (site, group, etc.) in the system, works with the site/group entities and the user entities. In the documentation below, a membership ID is a string in the form USER_ID::LOCATION_REFERENCE (e.g., "aaronz::site:mySiteId").</summary>
      <collectionURL>/membership</collectionURL>
      <collectionDescription>By default, retrieves a list of all site memberships for the current user. Optional query parameters: "includeSites=false" filters out site memberships; "includeGroups=true" retrieves group memberships; "_locationReference=LOCATION_REFERENCE" returns all memberships in the specified site or group; "user=USER_ID" (or "userId=USER_ID" or "_userReference=USER_REFERENCE") returns the given user's memberships; "includeMemberDetails=true" to return member full details of just the role of the user, cannot use this with includeGroups=true; "role=ROLE_STRING" (or "roleId=ROLE_STRING") restricts the list to the specified member role.</collectionDescription>
      <createURL>/membership/new</createURL>
      <createDescription>(POST) Add the membership specified by the ID. Alternatively, a POST to the simple "/membership" URL can specify "userId" and "locationReference" request parameters. In either case, optional request parameters are: "memberRole" string (default for joinable site memberships is the default joiner role); "active" Boolean value (default is true). Can do a batch add to the same location using the same role by specifying a "userIds" parameter (an array of user IDs).</createDescription>
      <showURL>/membership/:ID:</showURL>
      <updateURL>/membership/:ID:/edit</updateURL>
      <updateDescription>(POST) Modify the membership specified by the ID. Alternatively, a POST to the "/membership" URL can specify "userId" and "locationReference" request parameters. In either case, optional request parameters are: "memberRole" string; "active" Boolean value. Can do a batch update to the same location using the same role and active setting by specifying a "userIds" parameter (an array of user IDs).</updateDescription>
      <deleteURL>/membership/:ID:/delete</deleteURL>
      <deleteDescription>(DELETE) Delete the membership specified by the ID. Multiple memberships can be deleted from the same location by specifying a "userIds" parameter (an array of user IDs).</deleteDescription>
      <customActions>
        <customAction>
          <action>site</action>
          <url>/direct/membership/site</url>
          <method/>
          <viewKey/>
          <description>The URL format is "/membership/site/:SITE_ID:". <br/> (GET) will return all memberships in the specified site. <br/> (POST) will add one or more site memberships via an array of "userSearchValues" request parameters (each of which is a user ID, user EID, or email address), along with a "memberRole" string (default for joinable site memberships is the default joiner role) and "active" Boolean value (default is true). Response headers may include "x-warning-not-found" (for a list of invalid userSearchValues) and "x-warning-already-members" (for a list of userSearchValues which were already site members).</description>
        </customAction>
      </customActions>
      <customActions>
        <customAction>
          <action>unjoin</action>
          <url>/direct/membership/unjoin</url>
          <method>POST</method>
          <viewKey>new</viewKey>
          <description>Allows a user without permissions in a site to unjoin from it, works with the current user only: /membership/unjoin/site/siteId</description>
        </customAction>
      </customActions>
      <customActions>
        <customAction>
          <action>sitebyjson</action>
          <url>/direct/membership/sitebyjson</url>
          <method>POST</method>
          <viewKey>new</viewKey>
          <description>The URL format is "/membership/sitebyjson/:SITE_ID:". <br/> (POST) will add one or more site memberships via an chunk of JSON supplied in the 'json' request parameter.<br/> <br/>The JSON needs to be formatted like this: <br/> <br/>[ {"id": "user1", "role": "access"}, {"id": "user2","role": "maintain"} ]<br/> <br/>Three response headers will be set:<br/> <br/><b>x-success-count</b>, which contains the number of successful additions<br/> <b>x-warning-not-found</b>, which contains a comma separated list of user ids which didn't exist<br/>  <b>x-warning-already-members</b>, which contains a comma separated list of user ids which were already in the site</description>
        </customAction>
      </customActions>
      <customActions>
        <customAction>
          <action>join</action>
          <url>/direct/membership/join</url>
          <method>POST</method>
          <viewKey>new</viewKey>
          <description>Allows a user without permissions in a site to join it, works with the current user only: /membership/join/site/siteId</description>
        </customAction>
      </customActions>
      <customActions>
        <customAction>
          <action>fastroles</action>
          <url>/direct/membership/fastroles</url>
          <method/>
          <viewKey/>
          <description>Allows for retrieval of current role in site only quickly. Use the format "/membership/fastroles/:userId:" (or userEid) or current user if none specified. A shortcut for includeMemberDetail=false.</description>
        </customAction>
      </customActions>
      <customActions>
        <customAction>
          <action>group</action>
          <url>/direct/membership/group</url>
          <method/>
          <viewKey/>
          <description>The URL format is "/membership/group/:groupId:" <br/> (GET) will return all memberships for a group. <br/> (POST) will update user group membership. Mandatory POST Parameters: 'userIds' a comma separated list of users (eid or id). 'action' can have values: update, add or remove. If update, replace the current membership with the provided list. If add, add the list to the existing membership, if remove, remove the list from the existing membership. </description>
        </customAction>
      </customActions>
      <outputFormats>
        <format>html</format>
        <format>xml</format>
        <format>json</format>
        <format>form</format>
       </outputFormats>
      <inputFormats>
        <format>html</format>
        <format>xml</format>
        <format>json</format>
       </inputFormats>
      <entityClass>
        <class>org.sakaiproject.entitybroker.providers.model.EntityMember</class>
        <type>bean</type>
        <fields>
          <field>
            <name>active</name>
            <type>boolean</type>
            <readable>true</readable>
            <writeable>true</writeable>
          </field>
          <field>
            <name>id</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>lastLoginTime</name>
            <type>java.util.Date</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>locationReference</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>true</writeable>
          </field>
          <field>
            <name>memberRole</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>true</writeable>
          </field>
          <field>
            <name>provided</name>
            <type>boolean</type>
            <readable>true</readable>
            <writeable>true</writeable>
          </field>
          <field>
            <name>userDisplayId</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>userDisplayName</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>userEid</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>userEmail</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>userFirstName</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>userId</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>true</writeable>
          </field>
          <field>
            <name>userLastName</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
          <field>
            <name>userSortName</name>
            <type>java.lang.String</type>
            <readable>true</readable>
            <writeable>false</writeable>
          </field>
        </fields>
      </entityClass>
      <capabilities>
        <capability>
          <name>CoreEntityProvider</name>
          <type>org.sakaiproject.entitybroker.entityprovider.CoreEntityProvider</type>
        </capability>
        <capability>
          <name>EntityProvider</name>
          <type>org.sakaiproject.entitybroker.entityprovider.EntityProvider</type>
        </capability>
        <capability>
          <name>ActionsExecutable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.ActionsExecutable</type>
        </capability>
        <capability>
          <name>CRUDable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.CRUDable</type>
        </capability>
        <capability>
          <name>CollectionResolvable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.CollectionResolvable</type>
        </capability>
        <capability>
          <name>Createable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Createable</type>
        </capability>
        <capability>
          <name>Deleteable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Deleteable</type>
        </capability>
        <capability>
          <name>Describeable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Describeable</type>
        </capability>
        <capability>
          <name>Inputable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Inputable</type>
        </capability>
        <capability>
          <name>Outputable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Outputable</type>
        </capability>
        <capability>
          <name>RESTful</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.RESTful</type>
        </capability>
        <capability>
          <name>Redirectable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Redirectable</type>
        </capability>
        <capability>
          <name>Resolvable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Resolvable</type>
        </capability>
        <capability>
          <name>Sampleable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Sampleable</type>
        </capability>
        <capability>
          <name>Saveable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Saveable</type>
        </capability>
        <capability>
          <name>Updateable</name>
          <type>org.sakaiproject.entitybroker.entityprovider.capabilities.Updateable</type>
        </capability>
      </capabilities>
    </prefix>
