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.document;
017
018import org.apache.commons.collections.CollectionUtils;
019import org.apache.commons.lang.StringUtils;
020import org.hibernate.annotations.Fetch;
021import org.hibernate.annotations.FetchMode;
022import org.hibernate.annotations.GenericGenerator;
023import org.hibernate.annotations.Parameter;
024import org.hibernate.annotations.Type;
025import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
026import org.kuali.rice.kim.api.KimConstants;
027import org.kuali.rice.kim.api.identity.employment.EntityEmployment;
028import org.kuali.rice.kim.api.role.Role;
029import org.kuali.rice.kim.api.services.KimApiServiceLocator;
030import org.kuali.rice.kim.api.type.KimType;
031import org.kuali.rice.kim.bo.ui.KimDocumentRoleMember;
032import org.kuali.rice.kim.bo.ui.KimDocumentRoleQualifier;
033import org.kuali.rice.kim.bo.ui.PersonDocumentAddress;
034import org.kuali.rice.kim.bo.ui.PersonDocumentAffiliation;
035import org.kuali.rice.kim.bo.ui.PersonDocumentCitizenship;
036import org.kuali.rice.kim.bo.ui.PersonDocumentEmail;
037import org.kuali.rice.kim.bo.ui.PersonDocumentEmploymentInfo;
038import org.kuali.rice.kim.bo.ui.PersonDocumentGroup;
039import org.kuali.rice.kim.bo.ui.PersonDocumentName;
040import org.kuali.rice.kim.bo.ui.PersonDocumentPhone;
041import org.kuali.rice.kim.bo.ui.PersonDocumentPrivacy;
042import org.kuali.rice.kim.bo.ui.PersonDocumentRole;
043import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMember;
044import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMemberQualifier;
045import org.kuali.rice.kim.impl.identity.principal.PrincipalBo;
046import org.kuali.rice.kim.impl.type.KimTypeAttributesHelper;
047import org.kuali.rice.kim.service.KIMServiceLocatorInternal;
048import org.kuali.rice.kim.service.UiDocumentService;
049import org.kuali.rice.kns.service.DocumentHelperService;
050import org.kuali.rice.kns.service.KNSServiceLocator;
051import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
052import org.kuali.rice.krad.service.SequenceAccessorService;
053import org.kuali.rice.krad.util.GlobalVariables;
054
055import javax.persistence.AssociationOverride;
056import javax.persistence.AssociationOverrides;
057import javax.persistence.AttributeOverride;
058import javax.persistence.AttributeOverrides;
059import javax.persistence.CascadeType;
060import javax.persistence.Column;
061import javax.persistence.Entity;
062import javax.persistence.FetchType;
063import javax.persistence.GeneratedValue;
064import javax.persistence.JoinColumn;
065import javax.persistence.OneToMany;
066import javax.persistence.OneToOne;
067import javax.persistence.Table;
068import javax.persistence.Transient;
069import java.util.ArrayList;
070import java.util.HashMap;
071import java.util.List;
072import java.util.Map;
073
074/**
075 * This is a description of what this class does - shyu don't forget to fill
076 * this in.
077 *
078 * @author Kuali Rice Team (rice.collab@kuali.org)
079 *
080 */
081@Entity
082@AttributeOverrides({
083        @AttributeOverride(name="documentNumber",column=@Column(name="FDOC_NBR"))
084})
085@AssociationOverrides({
086        @AssociationOverride(name="documentHeader",joinColumns=@JoinColumn(name="FDOC_NBR",referencedColumnName="DOC_HDR_ID",insertable=false,updatable=false))
087})
088@Table(name="KRIM_PERSON_DOCUMENT_T")
089public class IdentityManagementPersonDocument extends IdentityManagementKimDocument {
090
091    protected static final long serialVersionUID = -534993712085516925L;
092    // principal data
093    
094    @GeneratedValue(generator="KRIM_PRNCPL_ID_S")
095        @GenericGenerator(name="KRIM_PRNCPL_ID_S",strategy="org.kuali.rice.core.jpa.spring.RiceNumericStringSequenceStyleGenerator",parameters={
096                        @Parameter(name="sequence_name",value="KRIM_PRNCPL_ID_S"),
097                        @Parameter(name="value_column",value="id")
098                })
099        @Column(name="PRNCPL_ID")
100    protected String principalId;
101    @Column(name="PRNCPL_NM")
102    protected String principalName;
103    @GeneratedValue(generator="KRIM_ENTITY_ID_S")
104        @GenericGenerator(name="KRIM_ENTITY_ID_S",strategy="org.kuali.rice.core.jpa.spring.RiceNumericStringSequenceStyleGenerator",parameters={
105                        @Parameter(name="sequence_name",value="KRIM_ENTITY_ID_S"),
106                        @Parameter(name="value_column",value="id")
107                })
108        @Column(name="ENTITY_ID")
109    protected String entityId;
110    @Type(type="org.kuali.rice.krad.util.HibernateKualiHashType")
111    @Column(name="PRNCPL_PSWD")
112    protected String password;
113
114    protected String univId = "";
115    // affiliation data
116    @OneToMany(targetEntity=PersonDocumentAffiliation.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
117    @Fetch(value = FetchMode.SELECT)
118    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
119    protected List<PersonDocumentAffiliation> affiliations;
120
121    @Transient
122    protected String campusCode = "";
123    // external identifier data
124    @Transient
125    protected Map<String, String> externalIdentifiers = null;
126
127    @Column(name="ACTV_IND")
128        @Type(type="yes_no")
129    protected boolean active;
130
131    // citizenship
132    @Transient
133    protected List<PersonDocumentCitizenship> citizenships;
134    // protected List<DocEmploymentInfo> employmentInformations;
135    @OneToMany(targetEntity=PersonDocumentName.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
136    @Fetch(value = FetchMode.SELECT)
137    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
138    protected List<PersonDocumentName> names;
139    @OneToMany(targetEntity=PersonDocumentAddress.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
140    @Fetch(value = FetchMode.SELECT)
141    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
142    protected List<PersonDocumentAddress> addrs;
143    @OneToMany(targetEntity=PersonDocumentPhone.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
144    @Fetch(value = FetchMode.SELECT)
145    @JoinColumn(name="FDOC_NBR")
146    protected List<PersonDocumentPhone> phones;
147    @OneToMany(targetEntity=PersonDocumentEmail.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
148    @Fetch(value = FetchMode.SELECT)
149    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
150    protected List<PersonDocumentEmail> emails;
151    @OneToMany(targetEntity=PersonDocumentGroup.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
152    @Fetch(value = FetchMode.SELECT)
153    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
154    protected List<PersonDocumentGroup> groups;
155    @OneToMany(targetEntity=PersonDocumentRole.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
156    @Fetch(value = FetchMode.SELECT)
157    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
158    protected List<PersonDocumentRole> roles;
159
160    @OneToOne(targetEntity=PersonDocumentPrivacy.class, fetch=FetchType.EAGER, cascade={CascadeType.ALL})
161    @JoinColumn(name="FDOC_NBR",insertable=false,updatable=false)
162    protected PersonDocumentPrivacy privacy;
163
164    public IdentityManagementPersonDocument() {
165        affiliations = new ArrayList<PersonDocumentAffiliation>();
166        citizenships = new ArrayList<PersonDocumentCitizenship>();
167        // employmentInformations = new ArrayList<DocEmploymentInfo>();
168        names = new ArrayList<PersonDocumentName>();
169        addrs = new ArrayList<PersonDocumentAddress>();
170        phones = new ArrayList<PersonDocumentPhone>();
171        emails = new ArrayList<PersonDocumentEmail>();
172        groups = new ArrayList<PersonDocumentGroup>();
173        roles = new ArrayList<PersonDocumentRole>();
174        privacy = new PersonDocumentPrivacy();
175        this.active = true;
176        // privacy.setDocumentNumber(documentNumber);
177    }
178
179    public String getPrincipalId() {
180        return this.principalId;
181    }
182
183    public void setPrincipalId(String principalId) {
184        this.principalId = principalId;
185    }
186
187    public String getPrincipalName() {
188        return this.principalName;
189    }
190
191    /*
192     * sets the principal name.  
193     * Principal names are converted to lower case.
194     */
195    public void setPrincipalName(String principalName) {
196        this.principalName = principalName; // != null ? principalName.toLowerCase() : principalName ;
197    }
198
199    public String getEntityId() {
200        return this.entityId;
201    }
202
203    public void setEntityId(String entityId) {
204        this.entityId = entityId;
205    }
206
207    public List<PersonDocumentAffiliation> getAffiliations() {
208        return this.affiliations;
209    }
210
211    public void setAffiliations(List<PersonDocumentAffiliation> affiliations) {
212        this.affiliations = affiliations;
213    }
214
215    public String getCampusCode() {
216        return this.campusCode;
217    }
218
219    public void setCampusCode(String campusCode) {
220        this.campusCode = campusCode;
221    }
222
223    public Map<String, String> getExternalIdentifiers() {
224        return this.externalIdentifiers;
225    }
226
227    public void setExternalIdentifiers(Map<String, String> externalIdentifiers) {
228        this.externalIdentifiers = externalIdentifiers;
229    }
230
231    public String getPassword() {
232        return this.password;
233    }
234
235    public void setPassword(String password) {
236        this.password = password;
237    }
238
239    public boolean isActive() {
240        return this.active;
241    }
242
243    public void setActive(boolean active) {
244        this.active = active;
245    }
246
247    public List<PersonDocumentCitizenship> getCitizenships() {
248        return this.citizenships;
249    }
250
251    public void setCitizenships(List<PersonDocumentCitizenship> citizenships) {
252        this.citizenships = citizenships;
253    }
254
255    public List<PersonDocumentName> getNames() {
256        return this.names;
257    }
258
259    public void setNames(List<PersonDocumentName> names) {
260        this.names = names;
261    }
262
263    public List<PersonDocumentAddress> getAddrs() {
264        return this.addrs;
265    }
266
267    public void setAddrs(List<PersonDocumentAddress> addrs) {
268        this.addrs = addrs;
269    }
270
271    public List<PersonDocumentPhone> getPhones() {
272        return this.phones;
273    }
274
275    public void setPhones(List<PersonDocumentPhone> phones) {
276        this.phones = phones;
277    }
278
279    public List<PersonDocumentEmail> getEmails() {
280        return this.emails;
281    }
282
283    public void setEmails(List<PersonDocumentEmail> emails) {
284        this.emails = emails;
285    }
286
287    public void setGroups(List<PersonDocumentGroup> groups) {
288        this.groups = groups;
289    }
290
291    public List<PersonDocumentRole> getRoles() {
292        return this.roles;
293    }
294
295    public void setRoles(List<PersonDocumentRole> roles) {
296        this.roles = roles;
297    }
298
299    public List<PersonDocumentGroup> getGroups() {
300        return this.groups;
301    }
302
303    public String getUnivId() {
304        return this.univId;
305    }
306
307    public void setUnivId(String univId) {
308        this.univId = univId;
309    }
310
311    public PersonDocumentPrivacy getPrivacy() {
312        return this.privacy;
313    }
314
315    public void setPrivacy(PersonDocumentPrivacy privacy) {
316        this.privacy = privacy;
317    }
318
319    public void initializeDocumentForNewPerson() {
320        if(StringUtils.isBlank(this.principalId)){
321            this.principalId = getSequenceAccessorService().getNextAvailableSequenceNumber(KimConstants.SequenceNames.KRIM_PRNCPL_ID_S, this.getClass()).toString();
322        }
323        if(StringUtils.isBlank(this.entityId)){
324            this.entityId = getSequenceAccessorService().getNextAvailableSequenceNumber(KimConstants.SequenceNames.KRIM_ENTITY_ID_S, this.getClass()).toString();
325        }
326    }
327
328    @SuppressWarnings("unchecked")
329    @Override
330    public List buildListOfDeletionAwareLists() {
331        List managedLists = super.buildListOfDeletionAwareLists();
332        List<PersonDocumentEmploymentInfo> empInfos = new ArrayList<PersonDocumentEmploymentInfo>();
333        for (PersonDocumentAffiliation affiliation : getAffiliations()) {
334            empInfos.addAll(affiliation.getEmpInfos());
335        }
336
337        managedLists.add(empInfos);
338        managedLists.add(getAffiliations());
339        managedLists.add(getCitizenships());
340        managedLists.add(getPhones());
341        managedLists.add(getAddrs());
342        managedLists.add(getEmails());
343        managedLists.add(getNames());
344        managedLists.add(getGroups());
345        managedLists.add(getRoles());
346        return managedLists;
347    }
348
349    /**
350     * @see org.kuali.rice.krad.document.DocumentBase#doRouteStatusChange(org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange)
351     */
352    @Override
353    public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
354        super.doRouteStatusChange(statusChangeEvent);
355        if (getDocumentHeader().getWorkflowDocument().isProcessed()) {
356                setIfRolesEditable();
357            KIMServiceLocatorInternal.getUiDocumentService().saveEntityPerson(this);
358        }
359    }
360
361
362    @Override
363    public void prepareForSave(){
364        if (StringUtils.isBlank(getPrivacy().getDocumentNumber())) {
365            getPrivacy().setDocumentNumber(
366                    getDocumentNumber());
367        }
368        setEmployeeRecordIds();
369        for (PersonDocumentRole role : getRoles()) {
370                role.setDocumentNumber(getDocumentNumber());
371                //if (StringUtils.isEmpty(role.getRoleId())) {
372                //      SequenceAccessorService sas = getSequenceAccessorService();
373                        //      Long nextSeq = sas.getNextAvailableSequenceNumber(
374                        //                      "KRIM_ROLE_ID_S", this.getClass());
375                        //      String roleId = nextSeq.toString();
376                        //      role.setRoleId(roleId);
377                //}
378            for (KimDocumentRoleMember rolePrncpl : role.getRolePrncpls()) {
379                rolePrncpl.setDocumentNumber(getDocumentNumber());
380                rolePrncpl.setRoleId(role.getRoleId());
381                if (StringUtils.isEmpty(rolePrncpl.getRoleMemberId())) {
382                                SequenceAccessorService sas = getSequenceAccessorService();
383                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
384                                                        "KRIM_ROLE_MBR_ID_S", this.getClass());
385                                        String roleMemberId = nextSeq.toString();
386                                        rolePrncpl.setRoleMemberId(roleMemberId);
387                        }
388                for (KimDocumentRoleQualifier qualifier : rolePrncpl.getQualifiers()) {
389                    qualifier.setDocumentNumber(getDocumentNumber());
390                    qualifier.setKimTypId(role.getKimTypeId());
391                }
392            }
393        }
394        if(getDelegationMembers()!=null){
395            for(RoleDocumentDelegationMember delegationMember: getDelegationMembers()){
396                delegationMember.setDocumentNumber(getDocumentNumber());
397                for (RoleDocumentDelegationMemberQualifier qualifier: delegationMember.getQualifiers()) {
398                    qualifier.setDocumentNumber(getDocumentNumber());
399                    qualifier.setKimTypId(delegationMember.getRoleBo().getKimTypeId());
400                }
401                addDelegationMemberToDelegation(delegationMember);
402            }
403        }
404        if (getAddrs() != null) {
405                String entityAddressId;
406                for(PersonDocumentAddress address : getAddrs()) {
407                        address.setDocumentNumber(getDocumentNumber());
408                        if (StringUtils.isEmpty(address.getEntityAddressId())) {
409                                SequenceAccessorService sas = getSequenceAccessorService();
410                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
411                                                        "KRIM_ENTITY_ADDR_ID_S", this.getClass());
412                                        entityAddressId = nextSeq.toString();
413                                        address.setEntityAddressId(entityAddressId);
414                        }
415                }
416        }
417        if (getAffiliations() != null) {
418                String affiliationId;
419                for(PersonDocumentAffiliation affiliation : getAffiliations()) {
420                        affiliation.setDocumentNumber(getDocumentNumber());
421                        if (StringUtils.isEmpty(affiliation.getEntityAffiliationId())) {
422                                SequenceAccessorService sas = getSequenceAccessorService();
423                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
424                                                        "KRIM_ENTITY_AFLTN_ID_S", this.getClass());
425                                        affiliationId = nextSeq.toString();
426                                        affiliation.setEntityAffiliationId(affiliationId);
427                        }
428                }
429        }
430        if (getEmails() != null) {
431                String entityEmailId;
432                for(PersonDocumentEmail email : getEmails()) {
433                        email.setDocumentNumber(getDocumentNumber());
434                        if (StringUtils.isEmpty(email.getEntityEmailId())) {
435                                SequenceAccessorService sas = getSequenceAccessorService();
436                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
437                                                        "KRIM_ENTITY_EMAIL_ID_S", this.getClass());
438                                        entityEmailId = nextSeq.toString();
439                                        email.setEntityEmailId(entityEmailId);
440                        }
441                }
442        }
443        if (getGroups() != null) {
444                String groupMemberId;
445                for(PersonDocumentGroup group : getGroups()) {
446                        group.setDocumentNumber(getDocumentNumber());
447                        if (StringUtils.isEmpty(group.getGroupMemberId())) {
448                                SequenceAccessorService sas = getSequenceAccessorService();
449                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
450                                                        "KRIM_GRP_MBR_ID_S", this.getClass());
451                                        groupMemberId = nextSeq.toString();
452                                        group.setGroupMemberId(groupMemberId);
453                        }
454                }
455        }
456        if (getNames() != null) {
457                String entityNameId;
458                for(PersonDocumentName name : getNames()) {
459                        name.setDocumentNumber(getDocumentNumber());
460                        if (StringUtils.isEmpty(name.getEntityNameId())) {
461                                SequenceAccessorService sas = getSequenceAccessorService();
462                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
463                                                        "KRIM_ENTITY_NM_ID_S", this.getClass());
464                                        entityNameId = nextSeq.toString();
465                                        name.setEntityNameId(entityNameId);
466                        }
467                }
468        }
469        if (getPhones() != null) {
470                String entityPhoneId;
471                for(PersonDocumentPhone phone : getPhones()) {
472                        phone.setDocumentNumber(getDocumentNumber());
473                        if (StringUtils.isEmpty(phone.getEntityPhoneId())) {
474                                SequenceAccessorService sas = getSequenceAccessorService();
475                                        Long nextSeq = sas.getNextAvailableSequenceNumber(
476                                                        "KRIM_ENTITY_PHONE_ID_S", this.getClass());
477                                        entityPhoneId = nextSeq.toString();
478                                        phone.setEntityPhoneId(entityPhoneId);
479                        }
480                }
481        }
482        
483    }
484
485    protected void setEmployeeRecordIds(){
486        List<EntityEmployment> empInfos = getUiDocumentService().getEntityEmploymentInformationInfo(getEntityId());
487        for(PersonDocumentAffiliation affiliation: getAffiliations()) {
488            int employeeRecordCounter = CollectionUtils.isEmpty(empInfos) ? 0 : empInfos.size();
489            for(PersonDocumentEmploymentInfo empInfo: affiliation.getEmpInfos()){
490                if(CollectionUtils.isNotEmpty(empInfos)){
491                    for(EntityEmployment origEmpInfo: empInfos){
492                        if (origEmpInfo.getEmployeeId().equals(empInfo.getEntityEmploymentId())) {
493                            empInfo.setEmploymentRecordId(origEmpInfo.getEmploymentRecordId());
494                        }
495                    }
496                }
497                if(StringUtils.isEmpty(empInfo.getEmploymentRecordId())){
498                    employeeRecordCounter++;
499                    empInfo.setEmploymentRecordId(employeeRecordCounter+"");
500                }
501            }
502        }
503    }
504
505    public KimTypeAttributesHelper getKimTypeAttributesHelper(String roleId) {
506        Role role = KimApiServiceLocator.getRoleService().getRole(roleId);
507        KimType kimTypeInfo = KimApiServiceLocator.getKimTypeInfoService().getKimType(role.getKimTypeId());
508        return new KimTypeAttributesHelper(kimTypeInfo);
509        //addDelegationRoleKimTypeAttributeHelper(roleId, helper);
510    }
511
512        public void setIfRolesEditable(){
513                if(CollectionUtils.isNotEmpty(getRoles())){
514                        for(PersonDocumentRole role: getRoles()){
515                                role.setEditable(validAssignRole(role));
516                        }
517                }
518        }
519
520        public boolean validAssignRole(PersonDocumentRole role){
521        boolean rulePassed = true;
522        if(StringUtils.isNotEmpty(role.getNamespaceCode())){
523                Map<String,String> additionalPermissionDetails = new HashMap<String,String>();
524                additionalPermissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, role.getNamespaceCode());
525                additionalPermissionDetails.put(KimConstants.AttributeConstants.ROLE_NAME, role.getRoleName());
526                        if (!getDocumentHelperService().getDocumentAuthorizer(this).isAuthorizedByTemplate(
527                                        this,
528                                        KimConstants.NAMESPACE_CODE,
529                                        KimConstants.PermissionTemplateNames.ASSIGN_ROLE,
530                                        GlobalVariables.getUserSession().getPrincipalId(),
531                                        additionalPermissionDetails, null)){
532                    rulePassed = false;
533                        }
534        }
535        return rulePassed;
536        }
537
538        @Transient
539        protected transient DocumentHelperService documentHelperService;
540        @Transient
541        protected transient UiDocumentService uiDocumentService;
542
543        protected DocumentHelperService getDocumentHelperService() {
544            if ( documentHelperService == null ) {
545                documentHelperService = KNSServiceLocator.getDocumentHelperService();
546                }
547            return this.documentHelperService;
548        }
549
550        protected UiDocumentService getUiDocumentService() {
551            if (uiDocumentService == null ) {
552                uiDocumentService = KIMServiceLocatorInternal.getUiDocumentService();
553                }
554            return this.uiDocumentService;
555        }
556
557}