<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (c) 2010-2017 Evolveum
  ~
  ~ Licensed 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.
  -->

<!-- Resource definition for OpenDJ server.

     THIS IS LEGACY VERSION. This definition is using the legacy LDAP connector.

-->

<resource oid="ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"
          xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
          xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
          xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
          xmlns:mr="http://prism.evolveum.com/xml/ns/public/matching-rule-3"
          xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
          xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
          xmlns:func="http://midpoint.evolveum.com/xml/ns/public/function/basic-3"
          xmlns:my="http://whatever.com/my">

    <!-- Resource printable name -->
    <name>Legacy OpenDJ</name>

    <!-- Reference to the ICF LDAP connector. This is dynamic reference, it will be translated to
          OID during import. -->
    <connectorRef type="ConnectorType">
        <filter>
            <q:text>c:connectorType = "org.identityconnectors.ldap.LdapConnector"</q:text>
        </filter>
    </connectorRef>

    <!-- Resource configuration section -->
    <connectorConfiguration
            xmlns:icfcldap="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap-legacy/org.identityconnectors.ldap.LdapConnector"
            xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">

        <!-- Configuration specific for the LDAP connector -->
        <icfc:configurationProperties>

            <icfcldap:port>389</icfcldap:port>
            <icfcldap:host>localhost</icfcldap:host>
            <icfcldap:baseContexts>dc=example,dc=com</icfcldap:baseContexts>
            <icfcldap:principal>cn=directory manager</icfcldap:principal>
            <icfcldap:credentials>
                <clearValue>secret</clearValue>
            </icfcldap:credentials>
            <icfcldap:vlvSortAttribute>uid</icfcldap:vlvSortAttribute>
            <icfcldap:accountOperationalAttributes>ds-pwp-account-disabled</icfcldap:accountOperationalAttributes>
        </icfc:configurationProperties>

        <!-- Generic ICF configuration -->

        <icfc:connectorPoolConfiguration>
            <icfc:minEvictableIdleTimeMillis>120000</icfc:minEvictableIdleTimeMillis>

            <icfc:minIdle>1</icfc:minIdle>
            <icfc:maxIdle>10</icfc:maxIdle>
            <icfc:maxObjects>10</icfc:maxObjects>
            <icfc:maxWait>150000</icfc:maxWait>
        </icfc:connectorPoolConfiguration>

        <icfc:producerBufferSize>100</icfc:producerBufferSize>

        <icfc:timeouts>
            <icfc:create>-1</icfc:create>
            <icfc:get>-1</icfc:get>
            <icfc:update>-1</icfc:update>
            <icfc:delete>-1</icfc:delete>
            <icfc:test>-1</icfc:test>

            <icfc:scriptOnConnector>-1</icfc:scriptOnConnector>
            <icfc:scriptOnResource>-1</icfc:scriptOnResource>
            <icfc:authentication>-1</icfc:authentication>
            <icfc:search>-1</icfc:search>
            <icfc:validate>-1</icfc:validate>
            <icfc:sync>-1</icfc:sync>

            <icfc:schema>-1</icfc:schema>
        </icfc:timeouts>

    </connectorConfiguration>

    <!-- No schema. It will be generated from the resource. -->

    <schemaHandling>

        <!-- Definition of default account type.
This is now the only account type that midPoint can work with. -->

        <objectType>
            <kind>account</kind>
            <intent>default</intent>
            <!-- Readable name for the account type -->
            <displayName>Default Account</displayName>

            <default>true</default>
            <!-- Reference to the Resource Schema specifying
      object class for this account type -->

            <objectClass>ri:AccountObjectClass</objectClass>

            <!-- Definition of __NAME__ attribute handling.
     ICF will put entry DN into __NAME__ attribute.-->
            <attribute>
                <ref>icfs:name</ref>

                <!-- Readable name for the attribute. This will be used in GUI -->
                <displayName>Distinguished Name</displayName>

                <matchingRule>mr:stringIgnoreCase</matchingRule>

                <!-- Outbound expression for the __NAME__ attribute.
      If account is created or updated, the __NAME__ attribute
      will be set accrding to this expression.

      This specific expression will construct DN by concatenating
      name from user object and string constants.

      The expression is marked as "default", therefore it will
      be evaluated only if the entry already does not have an DN.

      It is an XPath expression, similar to BPEL assignment expressions. -->
                <outbound>
                    <!-- Name cannot be weak. Changes in name trigger object rename. -->
                    <source>
                        <path>declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name</path>
                    </source>
                    <expression>
                        <script>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <code>
                                declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                concat('uid=', $i:name, ',ou=people,dc=example,dc=com')
                            </code>
                        </script>
                    </expression>
                </outbound>

                <!-- No inbound expression here. We cannot sync changes in DN yet -->

            </attribute>

            <!-- Definition of __UID__ attribute handling.
           ICF will put entry UUID into __UID__ attribute in case it
           is connecting to OpenDJ/OpenDS. It may be different for
           other directory servers and it also dependes on connector
           configuration. Please see connector documentation for
           more details.-->
            <attribute>
                <ref>icfs:uid</ref>

                <!-- Readable name for the attribute. This will be used in GUI -->
                <displayName>Entry UUID</displayName>

                <!-- There is no "outbound" expression, so midPoint will not
           do anything with this attribute. -->

                <!-- No inbound expression here. Does not make sense to sync UUID as it is supposed to be immutable -->

                <matchingRule>mr:stringIgnoreCase</matchingRule>

            </attribute>

            <!-- Definition of cn attribute handling. -->
            <attribute>

                <ref>ri:cn</ref>
                <displayName>Common Name</displayName>

                <!-- Outbound expression here is using "pure" XPath, without
                    using functions. This is the simplest case, just copying
                    the "fullName" property of user to the "cn" attribute of
                    an account.

                    Please note that this expression is not marked as "default".
                    Therefore this value will be copied on every change,
                    overwriting the original value of "cn" on the resource.
                -->

                <outbound>
                    <source>
                        <path>
                        declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                            $user/fullName
                        </path>
                    </source>
                </outbound>

                <!-- Inbound expression. It is used to synchronize changes
                    in the account to the user object in the IDM. This
                    expression specifies to copy the cn attribute value
                    from the account to the fullName property of the user.
                -->
                <inbound>
                    <expression>
                        <script>
                            <relativityMode>absolute</relativityMode>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <code>
                                declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                 declare namespace icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3";
                                 func:determineLdapSingleAttributeValue($c:account/c:attributes/icfs:name, 'cn', $c:input)
                             </code>
                        </script>
                    </expression>
                    <target>
                        <path>
                            declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                            $i:user/i:fullName
                        </path>
                    </target>
                </inbound>

            </attribute>

            <!-- Definition of sn attribute handling. -->
            <attribute>
                <ref>ri:sn</ref>

                <displayName>Surname</displayName>

                <outbound>
                    <source>
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:familyName</path>
                    </source>
                    <expression>
                        <script>
                            <description>
                                The expression is using "c" and "t" prefixes without declaring it. The prefix is taken from
                                the enclosing XML definition.
                            </description>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <code>
                            declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                $c:familyName
                            </code>
                        </script>
                    </expression>
                </outbound>
                <!-- sn will be synchronized to user's familyName -->
                <inbound>
                    <expression>
                        <script>
                            <relativityMode>absolute</relativityMode>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <code>
                                declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                 declare namespace icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3";
                                 func:determineLdapSingleAttributeValue($c:account/c:attributes/icfs:name, 'sn', $c:input)
                             </code>
                        </script>
                    </expression>
                    <target>
                        <!-- Relative path, we want to test the default target context which is $user -->
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";familyName</path>
                    </target>
                </inbound>

            </attribute>

            <!-- Definition of givenName attribute handling. -->
            <attribute>
                <ref>ri:givenName</ref>
                <displayName>Given Name</displayName>
                <outbound>
                    <description>
                        The mapping is using relative path in default source context (which is $user)
                        and default expression (which is asIs).
                    </description>
                    <source>
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";givenName</path>
                    </source>
                </outbound>
                <!-- givenName will be synchronized to user's givenName -->

                <inbound>
                    <expression>
                        <script>
                            <relativityMode>absolute</relativityMode>
                            <language>http://www.w3.org/TR/xpath/</language>
                             <code>
                                 declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                 declare namespace icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3";
                                 func:determineLdapSingleAttributeValue($c:account/c:attributes/icfs:name, 'givenName', $c:input)</code>
<!--                            <code>func:logDebug($c:account/c:attributes/icfs:name, 'givenName', $c:input)</code> -->
                        </script>
                    </expression>
                    <target>
                        <path>
                            declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                            $user/givenName
                        </path>
                    </target>
                </inbound>
            </attribute>

            <!-- Definition of uid attribute handling.
       Do not confuse with __UID__! -->
            <attribute>
                <ref>ri:uid</ref>

                <displayName>Login Name</displayName>

                <matchingRule>mr:stringIgnoreCase</matchingRule>

                <outbound>
                    <description>
                        It is mapped from (and also to) "name" property of user. It is essentially a login name.
                        This outbound construction is using a Groovy expression.
                    </description>
                    <!-- This MUST be weak in case of OpenDJ. If DN (name) is changed then the uid will be changed
                         as a side-effect as it is a naming attribute. -->
                    <strength>weak</strength>
                    <source>
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name</path>
                    </source>
                    <expression>
                        <script>
                            <language>http://midpoint.evolveum.com/xml/ns/public/expression/language#Groovy</language>
                            <code>
                                name;
                            </code>
                        </script>
                    </expression>
                </outbound>
                <inbound>
                    <description>
                        It is mapped to (and also from) "name" property of user. It is essentially a login name
                    </description>
                    <strength>weak</strength>
                    <expression>
                        <script>
                            <relativityMode>absolute</relativityMode>
                            <language>http://midpoint.evolveum.com/xml/ns/public/expression/language#Groovy</language>
                            <code>
                                basic.determineLdapSingleAttributeValue(
                                    basic.getAttributeStringValues(account, 'http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3', 'name'),
                                    'uid', (java.util.Collection) input)
                            </code>
                        </script>
                       </expression>
                    <target>
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name</path>
                    </target>
                </inbound>

            </attribute>

            <!-- Definition of description attribute handling. -->
            <attribute>
                <ref>ri:description</ref>

                <!-- This outbound expression is not really an expression.
              It is using a fixed literal insead of dynamically
              generated value. -->
                <outbound>
                    <strength>weak</strength>
                    <expression>
                        <value>Created by IDM</value>
                    </expression>
                </outbound>

                <inbound>
                    <target>
                        <path>
                            declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                            declare namespace my="http://whatever.com/my";
                            $i:user/i:extension/my:description
                        </path>
                    </target>
                </inbound>
                <!-- No inbound expression for description. We don't want to synchronize that -->
            </attribute>


            <attribute>
                <ref>ri:carLicense</ref>

                <description>
                    This attibute definition is used to test tolerance of empty values.
                </description>

                <outbound>
                    <description>
                        The expression will produce empty value. OpenDJ will die if empty value
                        is provided for an attribute. midPoint should filter out the empty value
                        and do not sent it to OpenDJ.
                    </description>
                    <strength>weak</strength>
                    <expression>
                        <script>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <returnType>scalar</returnType>
                            <c:code>
                                concat('','')
                            </c:code>
                        </script>
                    </expression>
                </outbound>

                <inbound>
                    <target>
                        <path>
                            declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                            declare namespace my="http://whatever.com/my";
                            $i:user/i:extension/my:description
                        </path>
                    </target>
                </inbound>
                <!-- No inbound expression for description. We don't want to synchronize that -->
            </attribute>

            <attribute>
                <ref>ri:employeeType</ref>

                <description>
                    This attibute definition is used to test inboud mapping when deleting the value from attribute.
                </description>

               <inbound>
<!--                <strength>strong</strength> -->
                    <target>
                          <path>declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/subtype</path>
                    </target>
                </inbound>
                <!-- No inbound expression for description. We don't want to synchronize that -->
            </attribute>

            <attribute>
                <ref>ri:displayName</ref>
                <displayName>Display Name</displayName>
                <outbound>
                    <description>
                        It is mapped from "fullName" property of user using ECMAScript (JavaScript) expression.
                    </description>
                    <source>
                        <path>$user/fullName</path>
                    </source>
                    <expression>
                        <script>
                            <language>http://midpoint.evolveum.com/xml/ns/public/expression/language#ECMAScript</language>
                            <code>
                                user == null ? null : user.getFullName();
                            </code>
                        </script>
                    </expression>
                </outbound>
            </attribute>

            <attribute>
                <ref>ri:postalAddress</ref>
                <displayName>Display Name</displayName>
                <outbound>
                    <description>
                        Conditional expression. It will be evaluated only if user's employee number is set.
                    </description>
                    <source>
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:employeeNumber</path>
                    </source>
                    <expression>
                        <script>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <returnType>scalar</returnType>
                            <code>
                                declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                concat('Number ',$c:employeeNumber)
                            </code>
                        </script>
                    </expression>
                    <condition>
                        <script>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <code>
                            declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                $c:user/c:employeeNumber
                            </code>
                        </script>
                    </condition>
                </outbound>
            </attribute>

            <!-- Definition of description attribute handling. -->
            <!-- This attribute is using a lookup table to translate the values
 valid for user to a values valid for the resource account. -->
            <attribute>
                <ref>ri:l</ref>
                <c:tolerant>false</c:tolerant>

                <!-- Outbound expression definition. This expression is using
              a configuration object (set into an XPath variable) to
              translate values. -->
                <outbound>
                    <strength>strong</strength>
                    <source>
                        <path>declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:locality</path>
                    </source>
                    <expression>
                        <script>
                            <c:language>http://www.w3.org/TR/xpath/</c:language>
                            <c:returnType>scalar</c:returnType>
                            <code>
                                declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                if (empty($c:user/c:locality)) then
                                    "middle of nowhere"
                                else
                                    $c:user/c:locality
                            </code>
                        </script>
                    </expression>
                    <!-- <expression xmlns:my="http://whatever.com/my"> -->
                        <!-- Definition of extra variable for the XPath expression.
                             The variable will appear as "$my:config" in the Xpath
                             expression below. It will contain the content of XML
                             object stored by OID c0c010c0-d34d-b33f-f00d-999111111111.-->
                        <!-- <variable>
                            <name>my:config</name>
                            <objectRef oid="c0c010c0-d34d-b33f-f00d-999111111111" type="c:GenericObjectType"/>
                        </variable> -->
                        <!-- Example of setting a variable to a string value. -->
                        <!-- <variable>
                            <name>my:defaultLocation</name>
                            <value>middle of nowhere</value>
                        </variable>
                        <script>
                            <c:relativityMode>absolute</c:relativityMode>
                            <language>http://www.w3.org/TR/xpath/</language>
                            <returnType>scalar</returnType> -->
                            <!-- The expression itself. It translates the value of
                                 user's attribute "locality" (expressed as $i:user/i:locality)
                                 using a lookup table defined in the configuration object
                                 in the $my:config variable specified above. -->
                            <!-- <c:code>
                                declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3";
                                declare namespace t="http://prism.evolveum.com/xml/ns/public/types-3";
                                declare namespace my="http://whatever.com/my";

                                if ($my:config/i:extension/my:locations/my:location[@key=$i:locality/t:orig]) then
                                    $my:config/i:extension/my:locations/my:location[@key=$i:locality/t:orig]
                                else
                                    $my:defaultLocation
                            </c:code>
                        </script>
                    </expression>-->

                </outbound>
            </attribute>

            <association>
                <ref>ri:group</ref>
                <displayName>LDAP Group Membership</displayName>
                <kind>entitlement</kind>
                <intent>ldapGroup</intent>
                <direction>objectToSubject</direction>
                <associationAttribute>ri:uniqueMember</associationAttribute>
                <valueAttribute>icfs:name</valueAttribute>
            </association>

            <activation>
                <administrativeStatus>
                    <!-- Empty outbound and inbound should do just fine in this case -->
                    <outbound/>
                    <inbound/>
                </administrativeStatus>
            </activation>

            <credentials>
                <password>
                    <outbound>
                        <expression>
                            <asIs/>
                        </expression>
                    </outbound>
                    <inbound>
                    <channel>http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService</channel>
<!--                         <strength>weak</strength>  -->
                        <expression>
<!--                              <generate/>  -->
                            <asIs/>
                        </expression>
                    </inbound>
                    <inbound>
                    <strength>weak</strength>
                    <exceptChannel>http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService</exceptChannel>
                        <expression>
                            <generate/>
<!--                             <asIs/> -->
                        </expression>
                    </inbound>
                </password>
            </credentials>

        </objectType>

        <objectType>
            <kind>entitlement</kind>
            <intent>ldapGroup</intent>
            <displayName>LDAP Group</displayName>
            <objectClass>ri:GroupObjectClass</objectClass>
        </objectType>

    </schemaHandling>

    <capabilities xmlns:cap="http://midpoint.evolveum.com/xml/ns/public/resource/capabilities-3">
        <configured>
            <cap:activation>
                <cap:status>
                    <cap:attribute>ri:ds-pwp-account-disabled</cap:attribute>
                    <cap:enableValue/>
                    <cap:disableValue>true</cap:disableValue>
                </cap:status>
            </cap:activation>
        </configured>
    </capabilities>

    <!--
        Synchronization section describes the synchronization policy, timing,
        reactions and similar synchronization settings.
    -->
    <c:synchronization>
        <objectSynchronization>
            <!--
        The synchronization for this resource is enabled.
        It means that the synchronization will poll for changes once
        per interval specified below. -->
            <c:enabled>true</c:enabled>

            <!-- Correlation expression.
               It will be used to find appropriate user entry for an account.
            -->
            <c:correlation> <!-- Correlation rule is a search query -->

                <!-- The clause <c:type uri="http://midpoint.evolveum.com/xml/ns/public/common/common-3#UserType"/> is implicit in correlation rules -->
                <!-- Following search query will look for users that have "name"
    equal to the "uid" attribute of the account. Simply speaking,
    it will look for match in usernames in the IDM and the resource. -->
                <q:equal>
                    <q:path>c:name</q:path>
                    <expression>
                        <path>$projection/c:attributes/ri:uid</path>
                    </expression>
                </q:equal>
            </c:correlation>

            <!-- Confirmation rule may be here, but as the search above will
    always return at most one match, the confirmation rule is not needed. -->

            <!-- Reference to the User Template is here. If the user would be
                 created as a result of this action, it will be created according
                 to this template. -->
            <objectTemplateRef oid="c0c010c0-d34d-b33f-f00d-777111111111"/>


            <!-- Following section describes reactions to a situations.
                The setting here assumes that this resource is authoritative,
                therefore all accounts created on the resource should be
                reflected as new users in IDM.
                See http://wiki.evolveum.com/display/midPoint/Synchronization+Situations
            -->
            <reaction>
                <situation>linked</situation>
                <synchronize>true</synchronize>
            </reaction>
            <reaction>
                <situation>deleted</situation>
                <synchronize>true</synchronize>
                <action>
                    <handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink</handlerUri>
                </action>
            </reaction>
            <reaction>
                <situation>unlinked</situation>
                <synchronize>true</synchronize>
                <action>
                    <handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
                </action>
            </reaction>
            <reaction>
                <situation>unmatched</situation>
                <synchronize>true</synchronize>
                <action>
                    <handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus</handlerUri>
                </action>
            </reaction>
        </objectSynchronization>
    </c:synchronization>

</resource>
