001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kim.impl.role;
017
018import java.sql.Timestamp;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import javax.persistence.CascadeType;
025import javax.persistence.Column;
026import javax.persistence.Entity;
027import javax.persistence.GeneratedValue;
028import javax.persistence.Id;
029import javax.persistence.JoinColumn;
030import javax.persistence.OneToMany;
031import javax.persistence.Table;
032import javax.persistence.Transient;
033
034import org.apache.commons.collections.CollectionUtils;
035import org.apache.commons.lang.ObjectUtils;
036import org.apache.commons.lang.StringUtils;
037import org.kuali.rice.core.api.membership.MemberType;
038import org.kuali.rice.kim.api.group.Group;
039import org.kuali.rice.kim.api.group.GroupContract;
040import org.kuali.rice.kim.api.identity.principal.Principal;
041import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
042import org.kuali.rice.kim.api.role.Role;
043import org.kuali.rice.kim.api.role.RoleContract;
044import org.kuali.rice.kim.api.role.RoleMember;
045import org.kuali.rice.kim.api.role.RoleMemberContract;
046import org.kuali.rice.kim.api.role.RoleResponsibilityAction;
047import org.kuali.rice.kim.api.services.KimApiServiceLocator;
048import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo;
049import org.kuali.rice.kim.impl.membership.AbstractMemberBo;
050import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator;
051import org.springframework.util.AutoPopulatingList;
052
053/**
054 * The column names have been used in a native query in RoleDaoOjb and will need to be modified if any changes to the
055 * column names are made here.
056 */
057@Entity
058@Table(name = "KRIM_ROLE_MBR_T")
059public class RoleMemberBo extends AbstractMemberBo implements RoleMemberContract {
060
061    private static final long serialVersionUID = 1L;
062
063    @PortableSequenceGenerator(name = "KRIM_ROLE_MBR_ID_S")
064    @GeneratedValue(generator = "KRIM_ROLE_MBR_ID_S")
065    @Id
066    @Column(name = "ROLE_MBR_ID")
067    private String id;
068
069    @Column(name = "ROLE_ID")
070    private String roleId;
071
072    @OneToMany(targetEntity = RoleMemberAttributeDataBo.class, orphanRemoval = true, cascade = { CascadeType.ALL })
073    @JoinColumn(name = "ROLE_MBR_ID", referencedColumnName = "ROLE_MBR_ID")
074    private List<RoleMemberAttributeDataBo> attributeDetails;
075
076    @Transient
077    private List<RoleResponsibilityActionBo> roleRspActions;
078
079    @Transient
080    private Map<String, String> attributes;
081
082    @Transient
083    protected String memberName;
084
085    @Transient
086    protected String memberNamespaceCode;
087
088    public List<RoleMemberAttributeDataBo> getAttributeDetails() {
089        if (this.attributeDetails == null) {
090            return new AutoPopulatingList<RoleMemberAttributeDataBo>(RoleMemberAttributeDataBo.class);
091        }
092        return this.attributeDetails;
093    }
094
095    public void setAttributeDetails(List<RoleMemberAttributeDataBo> attributeDetails) {
096        this.attributeDetails = attributeDetails;
097    }
098
099    @Override
100    public Map<String, String> getAttributes() {
101        return attributeDetails != null ? KimAttributeDataBo.toAttributes(attributeDetails) : attributes;
102    }
103
104    public static RoleMember to(RoleMemberBo bo) {
105        if (bo == null) {
106            return null;
107        }
108        return RoleMember.Builder.create(bo).build();
109    }
110
111    public static RoleMemberBo from(RoleMember immutable) {
112        if (immutable == null) {
113            return null;
114        }
115        RoleMemberBo bo = new RoleMemberBo();
116        bo.memberName = immutable.getMemberName();
117        bo.memberNamespaceCode = immutable.getMemberNamespaceCode();
118        bo.setId(immutable.getId());
119        bo.setRoleId(immutable.getRoleId());
120        List<RoleResponsibilityActionBo> actions = new ArrayList<RoleResponsibilityActionBo>();
121        if (CollectionUtils.isNotEmpty(immutable.getRoleRspActions())) {
122            for (RoleResponsibilityAction roleRespActn : immutable.getRoleRspActions()) {
123                actions.add(RoleResponsibilityActionBo.from(roleRespActn));
124            }
125        }
126        bo.setRoleRspActions(actions);
127        bo.setMemberId(immutable.getMemberId());
128        bo.setTypeCode(immutable.getType().getCode());
129        bo.setActiveFromDateValue(immutable.getActiveFromDate() == null ? null : new Timestamp(immutable.getActiveFromDate().getMillis()));
130        bo.setActiveToDateValue(immutable.getActiveToDate() == null ? null : new Timestamp(immutable.getActiveToDate().getMillis()));
131        bo.setObjectId(immutable.getObjectId());
132        bo.setVersionNumber(immutable.getVersionNumber());
133        return bo;
134    }
135
136    protected Object getMember(MemberType memberType, String memberId) {
137        if (MemberType.PRINCIPAL.equals(memberType)) {
138            return KimApiServiceLocator.getIdentityService().getPrincipal(memberId);
139        } else if (MemberType.GROUP.equals(memberType)) {
140            return KimApiServiceLocator.getGroupService().getGroup(memberId);
141        } else if (MemberType.ROLE.equals(memberType)) {
142            return KimApiServiceLocator.getRoleService().getRole(memberId);
143        }
144        return null;
145    }
146
147    @Override
148    public String getMemberName() {
149        if (getType() == null || StringUtils.isEmpty(getMemberId())) {
150            return "";
151        }
152        Object member = getMember(getType(), getMemberId());
153        if (member == null) {
154            this.memberName = "";
155            Principal kp = KimApiServiceLocator.getIdentityService().getPrincipal(getMemberId());
156            if (kp != null && kp.getPrincipalName() != null && !"".equals(kp.getPrincipalName())) {
157                this.memberName = kp.getPrincipalName();
158            }
159            return this.memberName;
160        }
161        return getRoleMemberName(getType(), member);
162    }
163
164    public String getRoleMemberName(MemberType memberType, Object member) {
165        String roleMemberName = "";
166        if (MemberType.PRINCIPAL.equals(memberType)) {
167            roleMemberName = ((PrincipalContract) member).getPrincipalName();
168        } else if (MemberType.GROUP.equals(memberType)) {
169            roleMemberName = ((GroupContract) member).getName();
170        } else if (MemberType.ROLE.equals(memberType)) {
171            roleMemberName = ((RoleContract) member).getName();
172        }
173        return roleMemberName;
174    }
175
176    @Override
177    public String getMemberNamespaceCode() {
178        if (getType() == null || StringUtils.isEmpty(getMemberId())) {
179            return "";
180        }
181        this.memberNamespaceCode = "";
182        if (MemberType.PRINCIPAL.equals(getType())) {
183            this.memberNamespaceCode = "";
184        } else if (MemberType.GROUP.equals(getType())) {
185            Group groupInfo = KimApiServiceLocator.getGroupService().getGroup(getMemberId());
186            if (groupInfo != null) {
187                this.memberNamespaceCode = groupInfo.getNamespaceCode();
188            }
189        } else if (MemberType.ROLE.equals(getType())) {
190            Role role = KimApiServiceLocator.getRoleService().getRole(getMemberId());
191            if (role != null) {
192                this.memberNamespaceCode = role.getNamespaceCode();
193            }
194        }
195        return this.memberNamespaceCode;
196    }
197
198    /**
199     * This method compares role member passed with this role member object and returns true if no differences or returns
200     * false.
201     *
202     * @param targetMbrBo
203     * @return boolean true if the member has not changed, false if the member has changed
204     */
205    public boolean equals(RoleMemberBo targetMbrBo) {
206        if (!StringUtils.equals(getId(), targetMbrBo.getId())) {
207            return false;
208        }
209        if (!StringUtils.equals(getType().getCode(), targetMbrBo.getType().getCode())) {
210            return false;
211        }
212        if (!StringUtils.equals(getMemberId(), targetMbrBo.getMemberId())) {
213            return false;
214        }
215        if (!ObjectUtils.equals(getActiveFromDate(), targetMbrBo.getActiveFromDate())) {
216            return false;
217        }
218        if (!ObjectUtils.equals(getActiveToDate(), targetMbrBo.getActiveToDate())) {
219            return false;
220        }
221        // Prepare list of attributes from this role member eliminating blank attributes
222        Map<String, String> sourceMbrAttrDataList = new HashMap<String, String>();
223        for (Map.Entry<String, String> mbrAttr : getAttributes().entrySet()) {
224            if (StringUtils.isNotBlank(mbrAttr.getValue())) {
225                ((HashMap<String, String>) sourceMbrAttrDataList).put(mbrAttr.getKey(), mbrAttr.getValue());
226            }
227        }
228        // Prepare list of attributes from target role member eliminating blank attributes
229        Map<String, String> targetMbrAttrDataList = new HashMap<String, String>();
230        for (Map.Entry<String, String> mbrAttr : targetMbrBo.getAttributes().entrySet()) {
231            if (StringUtils.isNotBlank(mbrAttr.getValue())) {
232                ((HashMap<String, String>) targetMbrAttrDataList).put(mbrAttr.getKey(), mbrAttr.getValue());
233            }
234        }
235        if (targetMbrAttrDataList.size() != sourceMbrAttrDataList.size()) {
236            return false;
237        }
238        // Check if any attributes changed, then return false
239        Map<String, String> matchedAttrs = new HashMap<String, String>();
240        for (Map.Entry<String, String> newAttr : sourceMbrAttrDataList.entrySet()) {
241            for (Map.Entry<String, String> origAttr : targetMbrAttrDataList.entrySet()) {
242                if (StringUtils.equals(origAttr.getKey(), newAttr.getKey())) {
243                    if (StringUtils.equals(origAttr.getValue(), newAttr.getValue())) {
244                        ((HashMap<String, String>) matchedAttrs).put(newAttr.getKey(), newAttr.getValue());
245                    }
246                }
247            }
248        }
249        if (matchedAttrs.size() != sourceMbrAttrDataList.size()) {
250            return false;
251        }
252        // Check responsibility actions
253        int targetMbrActionsSize = (targetMbrBo.getRoleRspActions() == null) ? 0 : targetMbrBo.getRoleRspActions().size();
254        int sourceMbrActionsSize = (getRoleRspActions() == null) ? 0 : getRoleRspActions().size();
255        if (targetMbrActionsSize != sourceMbrActionsSize) {
256            return false;
257        }
258        if (sourceMbrActionsSize != 0) {
259            List<RoleResponsibilityActionBo> matchedRspActions = new ArrayList<RoleResponsibilityActionBo>();
260            // Check if any responsibility actions changed
261            for (RoleResponsibilityActionBo newAction : getRoleRspActions()) {
262                for (RoleResponsibilityActionBo origAction : targetMbrBo.getRoleRspActions()) {
263                    if (StringUtils.equals(origAction.getId(), newAction.getId())) {
264                        if (origAction.equals(newAction)) {
265                            matchedRspActions.add(newAction);
266                        }
267                    }
268                }
269            }
270            if (matchedRspActions.size() != getRoleRspActions().size()) {
271                return false;
272            }
273        }
274        return true;
275    }
276
277    @Override
278    public String getId() {
279        return id;
280    }
281
282    public void setId(String id) {
283        this.id = id;
284    }
285
286    @Override
287    public String getRoleId() {
288        return roleId;
289    }
290
291    public void setRoleId(String roleId) {
292        this.roleId = roleId;
293    }
294
295    @Override
296    public List<RoleResponsibilityActionBo> getRoleRspActions() {
297        if (this.roleRspActions == null) {
298            return new AutoPopulatingList<RoleResponsibilityActionBo>(RoleResponsibilityActionBo.class);
299        }
300        return this.roleRspActions;
301    }
302
303    public void setRoleRspActions(List<RoleResponsibilityActionBo> roleRspActions) {
304        this.roleRspActions = roleRspActions;
305    }
306
307    public void setAttributes(Map<String, String> attributes) {
308        this.attributes = attributes;
309    }
310}