<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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.
-->

<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">

    <simple-method method-name="workEffortManagerPermission" short-description="Check user has WorkEffort Manager permission">
        <set field="primaryPermission" value="WORKEFFORTMGR"/>
        <call-simple-method method-name="genericBasePermissionCheck" xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
    </simple-method>

    <simple-method method-name="workEffortGenericPermission" short-description="">
        <set field="primaryPermission" value="WORKEFFORTMGR"/>
        <call-simple-method method-name="genericBasePermissionCheck" xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
        <if>
            <condition>
                <not>
                    <if-compare field="hasPermission" value="true" operator="equals"/>
                </not>
            </condition>
            <then>
                <!-- The user does not have WORKEFFORTMGR permission -->
                <log level="info" message="The user does not have WORKEFFORTMGR permission"/>
                <set field="primaryPermission" value="WORKEFFORTMGR_ROLE"/>
                <call-simple-method method-name="genericBasePermissionCheck" xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
                <if>
                    <condition>
                        <if-compare field="hasPermission" value="true" operator="equals"/>
                    </condition>
                    <then>
                        <log level="info" message="User has ROLE permission, now checking if user is in required ROLE "></log>
                        <if>
                            <condition>
                                <and>
                                    <if-compare field="mainAction" value="CREATE" operator="equals"/>
                                    <not>
                                        <if-empty field="parameters.workEffortParentId"/>
                                    </not>
                                </and>
                            </condition>
                            <then>
                                <!-- check ANY role permission on the parent -->
                                <set field="workEffortId" from-field="parameters.workEffortParentId"/>
                                <call-simple-method method-name="workEffortPartyAnyRolePermission"/>
                            </then>
                        <else-if>
                            <!-- Processing UPDATE permission check  -->
                            <condition>
                                <if-compare field="mainAction" value="UPDATE" operator="equals"/>
                            </condition>
                            <then>
                                <!-- make sure we have role permission to update THIS workeffort -->
                                <set field="workEffortId" from-field="parameters.workEffortId"/>
                                <call-simple-method method-name="workEffortPartyOwnerRolePermission"/>
                                <!-- get the existing parent ID -->
                                <entity-one entity-name="WorkEffort" value-field="workEffort">
                                    <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
                                </entity-one>
                                <if>
                                    <condition>
                                        <and>
                                            <if-compare field="hasPermission" value="true" operator="equals"/>
                                            <not><if-empty field="parameters.workEffortParentId"/></not>
                                            <if-compare-field field="parameters.workEffortParentId" to-field="workEffort.workEffortParentId" operator="not-equals"/>
                                        </and>
                                    </condition>
                                    <then>
                                            <!-- check the parent -->
                                            <log level="info" message=" User is in Cal Owner role and can update, Now checking if user has access to parent workeffort "></log>
                                            <set field="workEffortId" from-field="parameters.workEffortParentId"/>
                                            <call-simple-method method-name="workEffortPartyOwnerRolePermission"/>
                                    </then>
                                </if>
                                <!-- Check for party Group -->
                                <if>
                                    <condition>
                                        <not>
                                            <if-compare field="hasPermission" value="true" operator="equals"/>
                                        </not>
                                    </condition>
                                    <then>
                                        <log level="info" message=" User does not have Direct access to this workeffort checking if its member of PartyGroup that has required permission "></log>
                                        <set field="workEffortId" from-field="parameters.workEffortId"/>
                                        <call-simple-method method-name="workEffortPartyGroupRolePermission"/>
                                        <if>
                                            <condition>
                                                <and>
                                                    <if-compare field="hasPermission" value="true" operator="equals"/>
                                                    <not><if-empty field="parameters.workEffortParentId"/></not>
                                                    <if-compare-field field="parameters.workEffortParentId" to-field="workEffort.workEffortParentId" operator="not-equals"/>
                                                </and>
                                            </condition>
                                            <then>
                                                <!-- check the parent -->
                                                <set field="workEffortId" from-field="parameters.workEffortParentId"/>
                                                <call-simple-method method-name="workEffortPartyGroupRolePermission"/>
                                            </then>
                                        </if>
                                    </then>
                                </if>
                            </then>
                        </else-if>
                        </if>
                    </then>
                </if>
            </then>
        </if>
    </simple-method>

    <simple-method method-name="workEffortPartyOwnerRolePermission" short-description="Check if Party is in CAL_OWNER or CAL_DELEGATE role with WorkEffort">
        <if-empty field="workEffortId">
            <!-- This should be case of create WorkEffort -->
            <set field="workEffortId" from-field="parameters.workEffortParentId"/>
        </if-empty>
        <while><condition><not><if-empty field="workEffortId"></if-empty></not></condition>
            <then>
                <!-- if the case is of new workEffort with Parent workEffort Id,
                    then lookup the parent workEffort and check if user  is in any OWNER role with WorkEffort -->
                <set from-field="workEffortId" field="lookupRoleWorkEffortMap.workEffortId"/>
                <set from-field="userLogin.partyId" field="lookupRoleWorkEffortMap.partyId"/>
                <set value="CAL_OWNER" field="lookupRoleWorkEffortMap.roleTypeId"/>
                <log level="info" message="Running find-by-and: ${lookupRoleWorkEffortMap}"/>

                <find-by-and entity-name="WorkEffortPartyAssignment" map="lookupRoleWorkEffortMap" list="roleParties"/>
                <filter-list-by-date list="roleParties"/>
                <log level="info" message="Found role parties: ${roleParties}"/>

                <if-empty field="roleParties">
                    <log level="info" message="Party ${userLogin.partyId} is not in ${roleTypeId} role with workEffort: ${workEffortId}"/>
                    <set value="CAL_DELEGATE" field="lookupRoleWorkEffortMap.roleTypeId"/>
                    <find-by-and entity-name="WorkEffortPartyAssignment" map="lookupRoleWorkEffortMap" list="roleParties"/>
                </if-empty>
                <filter-list-by-date list="roleParties"/>

                <if-not-empty field="roleParties">
                    <set field="hasPermission" type="Boolean" value="true"/>
                    <field-to-result field="hasPermission"/>
                    <log level="info" message="Party ${userLogin.partyId} is in ${lookupRoleWorkEffortMap.roleTypeId} role with workEffort: ${workEffortId}"/>
                    <clear-field field="workEffortId"/>

                    <else>
                        <log level="info" message="Party ${userLogin.partyId} is not in ${roleTypeId} role with workEffort: ${workEffortId}"/>
                        <property-to-field resource="WorkEffortUiLabels" property="WorkEffortNotInRolePermissionError" field="failMessage"/>
                        <set field="hasPermission" type="Boolean" value="false"/>
                        <field-to-result field="hasPermission"/>
                        <field-to-result field="failMessage"/>

                        <!-- recurse through all parents -->
                        <set field="workEffortLookUpMap.workEffortId" from-field="workEffortId"/>
                        <find-by-primary-key entity-name="WorkEffort" map="workEffortLookUpMap" value-field="workEffortParent"/>
                        <set from-field="workEffortParent.workEffortParentId" field="workEffortId"/>
                        <if-empty field="workEffortParent.workEffortParentId">
                            <clear-field field="workEffortId"/>
                        </if-empty>
                    </else>

                </if-not-empty>
            </then>
        </while>
    </simple-method>

    <simple-method method-name="workEffortPartyAnyRolePermission" short-description="Check if Party is in ANY role with WorkEffort">
        <if-empty field="workEffortId">
            <!-- This should be case of create WorkEffort -->
            <set field="workEffortId" from-field="parameters.workEffortParentId"/>
        </if-empty>
        <while><condition><not><if-empty field="workEffortId"></if-empty></not></condition>
            <then>
                <!-- if the case is of new workEffort with Parent workEffort Id,
                    then lookup the parent workEffort and check if user  is in any role with WorkEffort -->
                <set from-field="workEffortId" field="lookupRoleWorkEffortMap.workEffortId"/>
                <set from-field="userLogin.partyId" field="lookupRoleWorkEffortMap.partyId"/>
                <find-by-and entity-name="WorkEffortPartyAssignment" map="lookupRoleWorkEffortMap" list="roleParties"/>
                <filter-list-by-date list="roleParties"/>

                <if-not-empty field="roleParties">
                    <set field="hasPermission" type="Boolean" value="true"/>
                    <field-to-result field="hasPermission"/>
                    <log level="info" message="Party ${userLogin.partyId} is associated with workEffort: ${workEffortId}"/>
                    <clear-field field="workEffortId"/>

                    <else>
                        <log level="info" message="Party ${userLogin.partyId} is not associated with workEffort: ${workEffortId}"/>
                        <property-to-field resource="WorkEffortUiLabels" property="WorkEffortNotInRolePermissionError" field="failMessage"/>
                        <set field="hasPermission" type="Boolean" value="false"/>
                        <field-to-result field="hasPermission"/>
                        <field-to-result field="failMessage"/>

                        <!-- recurse through all parents -->
                        <set field="workEffortLookUpMap.workEffortId" from-field="workEffortId"/>
                        <find-by-primary-key entity-name="WorkEffort" map="workEffortLookUpMap" value-field="workEffortParent"/>
                        <set from-field="workEffortParent.workEffortParentId" field="workEffortId"/>
                        <if-empty field="workEffortParent.workEffortParentId">
                            <clear-field field="workEffortId"/>
                        </if-empty>
                    </else>

                </if-not-empty>
            </then>
        </while>
    </simple-method>

    <simple-method method-name="timesheetUpdatePermission" short-description="Check Permission to Update Timesheet">
        <set field="parameters.mainAction" value="UPDATE"/>
        <call-simple-method method-name="workEffortGenericPermission"/>
        <check-errors/>
        <if-compare-field field="parameters.partyId" operator="not-equals" to-field="userLogin.partyId">
            <property-to-field resource="WorkEffortUiLabels" property="WorkEffortTimesheetNotInRolePermissionError" field="failMessage"/>
            <set field="hasPermission" type="Boolean" value="false"/>
            <field-to-result field="hasPermission"/>
            <field-to-result field="failMessage"/>
        </if-compare-field>
        <if-not-empty field="workEffortId">
            <set from-field="workEffortId" field="lookupRoleWorkEffortMap.workEffortId"/>
            <set from-field="userLogin.partyId" field="lookupRoleWorkEffortMap.partyId"/>
            <find-by-and entity-name="WorkEffortPartyAssignByRole" map="lookupRoleWorkEffortMap" list="roleParties"/>
            <filter-list-by-date list="roleParties"/>
            <if-empty field="roleParties">
                <property-to-field resource="WorkEffortUiLabels" property="WorkEffortTimesheetNotInRolePermissionError" field="failMessage"/>
                <set field="hasPermission" type="Boolean" value="false"/>
                <field-to-result field="hasPermission"/>
                <field-to-result field="failMessage"/>
            </if-empty>
        </if-not-empty>
    </simple-method>

    <!-- check for party groups -->
    <!-- Get list of Party Groups in CAL_OWNER or CAL_DELEGATE with WorkEffort or its parents -->
    <simple-method method-name="workEffortPartyGroupRolePermission" short-description="Check if Party is party member of PartyGroup that is in CAL_OWNER or CAL_DELEGATE role with WorkEffort">
        <if-empty field="workEffortId">
            <!-- This should be case of create WorkEffort -->
            <set field="workEffortId" from-field="parameters.workEffortParentId"/>
        </if-empty>
        <while><condition><not><if-empty field="workEffortId"></if-empty></not></condition>
            <then>
                <!-- Get list of Parties of Type PartyGroup in CAL_OWNER or CAL_DELEGATE with WorkEffort -->
                <set from-field="workEffortId" field="lookupPartyRoleWorkEffortMap.workEffortId"/>
                <set value="CAL_OWNER" field="lookupPartyRoleWorkEffortMap.roleTypeId"/>
                <set value="PARTY_GROUP" field="lookupPartyRoleWorkEffortMap.partyTypeId"/>
                <log level="info" message="Running find-by-and: ${lookupPartyRoleWorkEffortMap}"/>

                <find-by-and entity-name="WorkEffortPartyAssignView" map="lookupPartyRoleWorkEffortMap" list="rolePartyGroups"/>
                <filter-list-by-date list="rolePartyGroups"/>
                <log level="info" message="Found role parties Group: ${rolePartyGroups}"/>

                <if-empty field="rolePartyGroups">
                    <log level="info" message="No Party Group found in CAL_OWNER role with workEffort: ${workEffortId}"/>
                    <set value="CAL_DELEGATE" field="lookupRoleWorkEffortMap.roleTypeId"/>
                    <find-by-and entity-name="WorkEffortPartyAssignView" map="lookupRoleWorkEffortMap" list="rolePartyGroups"/>
                </if-empty>
                <filter-list-by-date list="rolePartyGroups"/>
                <if-not-empty field="rolePartyGroups">
                    <!-- Check to see if User is member of any of these Party groups -->
                    <iterate list="rolePartyGroups" entry="rolePartyGroup">
                        <!-- check current party is the member of party group-->
                        <!-- PartyGroup partyId-->
                        <set from-field="rolePartyGroup.partyId" field="lookupPartyRoleMap.partyIdFrom"/>
                        <!-- logged party partyId-->
                        <set from-field="userLogin.partyId" field="lookupPartyRoleMap.partyIdTo"/>
                        <log level="info" message="Conditions: ${lookupPartyRoleMap}"/>
                        <find-by-and entity-name="PartyRelationship" map="lookupPartyRoleMap" list="partyGroupRelationships"/>
                        <log level="info" message="Found role parties relations: ${partyGroupRelationships}"/>
                        <if-not-empty field="partyGroupRelationships">
                            <set field="hasPermission" type="Boolean" value="true"/>
                            <field-to-result field="hasPermission"/>
                            <log level="info" message="Party ${userLogin.partyId} is associated with workEffort: ${workEffortId}"/>
                        </if-not-empty>
                    </iterate>
                    <clear-field field="workEffortId"/>
                <else>
                    <log level="info" message="Party ${userLogin.partyId} is not associated with workEffort: ${workEffortId}"/>
                    <property-to-field resource="WorkEffortUiLabels" property="WorkEffortNotInRolePermissionError" field="failMessage"/>
                    <set field="hasPermission" type="Boolean" value="false"/>
                    <field-to-result field="hasPermission"/>
                    <field-to-result field="failMessage"/>
                    <!-- recurse through all parents -->
                    <set field="workEffortLookUpMap.workEffortId" from-field="workEffortId"/>
                    <find-by-primary-key entity-name="WorkEffort" map="workEffortLookUpMap" value-field="workEffortParent"/>
                    <set from-field="workEffortParent.workEffortParentId" field="workEffortId"/>
                    <if-empty field="workEffortParent.workEffortParentId">
                        <clear-field field="workEffortId"/>
                    </if-empty>
                </else>
                </if-not-empty>
            </then>
        </while>
    </simple-method>

    <simple-method method-name="workEffortICalendarPermission" short-description="Check iCalendar Permission">
        <!-- Note: the iCalendar servlet will call the permission service under two conditions - to grant
             VIEW access to a calendar that isn't PUBLIC, or to grant CREATE or UPDATE access to a work effort -->
        <log level="verbose" message="workEffortICalendarPermission invoked for workEffortId ${parameters.workEffortId},
            user login partyId = ${userLogin.partyId}"/>
        <call-simple-method method-name="workEffortManagerPermission"/>
        <if>
            <condition>
                <and>
                    <if-compare field="hasPermission" value="true" operator="equals"/>
                    <not><if-empty field="parameters.workEffortId"/></not>
                </and>
            </condition>
            <then>
                <set field="hasPermission" value="false" type="Boolean"/>
                <set field="workEffortId" from-field="parameters.workEffortId"/>
                <entity-one entity-name="WorkEffort" value-field="workEffort"/>
                <if-not-empty field="workEffort">
                    <entity-condition entity-name="WorkEffortPartyAssignment" list="partyAssignments" filter-by-date="true">
                        <condition-list combine="and">
                            <condition-expr field-name="workEffortId" from-field="workEffortId"/>
                            <condition-expr field-name="partyId" from-field="userLogin.partyId"/>
                            <condition-expr field-name="statusId" value="PRTYASGN_ASSIGNED"/>
                            <condition-list combine="or">
                                <condition-expr field-name="roleTypeId" value="CAL_OWNER"/>
                                <condition-expr field-name="roleTypeId" value="CAL_ORGANIZER"/>
                                <condition-expr field-name="roleTypeId" value="CAL_DELEGATE"/>
                            </condition-list>
                        </condition-list>
                    </entity-condition>
                    <set field="isDelegate" value="false"/>
                    <set field="isOwner" value="false"/>
                    <set field="isOrganizer" value="false"/>
                    <iterate list="partyAssignments" entry="partyAssignment">
                        <if-compare field="partyAssignment.roleTypeId" operator="equals" value="CAL_OWNER">
                            <set field="isDelegate" value="true"/>
                            <set field="isOwner" value="true"/>
                            <set field="isOrganizer" value="true"/>
                        <else>
                            <if-compare field="partyAssignment.roleTypeId" operator="equals" value="CAL_ORGANIZER">
                                <set field="isOrganizer" value="true"/>
                                <else>
                                    <if-compare field="partyAssignment.roleTypeId" operator="equals" value="CAL_DELEGATE">
                                        <set field="isDelegate" value="true"/>
                                    </if-compare>
                                </else>
                            </if-compare>
                        </else>
                        </if-compare>
                    </iterate>
                    <if-compare field="workEffort.workEffortTypeId" operator="equals" value="PUBLISH_PROPS">
                        <log level="verbose" message="Checking publish properties permission, isOwner = ${isOwner}, isDelegate = ${isDelegate}"/>
                        <if>
                            <condition>
                                <or>
                                    <!-- The user is the calendar owner -->
                                    <if-compare field="isOwner" operator="equals" value="true"/>
                                    <and>
                                        <!-- The calendar is confidential and the user is a delegate of the calendar -->
                                        <if-compare field="workEffort.scopeEnumId" operator="equals" value="WES_CONFIDENTIAL"/>
                                        <if-compare field="isDelegate" operator="equals" value="true"/>
                                    </and>
                                </or>
                            </condition>
                        <then>
                            <set field="hasPermission" value="true" type="Boolean"/>
                        </then>
                        </if>
                    <else>
                        <!-- RFC 2445 3.5 Only an ORGANIZER can update a VEVENT or VTODO. -->
                        <log level="verbose" message="Checking work effort update permission, isOrganizer = ${isOrganizer}"/>
                        <if-compare field="isOrganizer" operator="equals" value="true">
                            <set field="hasPermission" value="true" type="Boolean"/>
                        </if-compare>
                    </else>
                    </if-compare>
                </if-not-empty>
                <field-to-result field="hasPermission"/>
            </then>
        </if>
    </simple-method>

</simple-methods>
