001    /**
002     * Copyright 2005-2014 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     */
016    package org.kuali.rice.kim.document;
017    
018    import org.apache.commons.collections.CollectionUtils;
019    import org.apache.commons.lang.StringUtils;
020    import org.hibernate.annotations.Fetch;
021    import org.hibernate.annotations.FetchMode;
022    import org.hibernate.annotations.GenericGenerator;
023    import org.hibernate.annotations.Parameter;
024    import org.hibernate.annotations.Type;
025    import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
026    import org.kuali.rice.kim.api.KimConstants;
027    import org.kuali.rice.kim.api.identity.employment.EntityEmployment;
028    import org.kuali.rice.kim.api.role.Role;
029    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
030    import org.kuali.rice.kim.api.type.KimType;
031    import org.kuali.rice.kim.bo.ui.KimDocumentRoleMember;
032    import org.kuali.rice.kim.bo.ui.KimDocumentRoleQualifier;
033    import org.kuali.rice.kim.bo.ui.PersonDocumentAddress;
034    import org.kuali.rice.kim.bo.ui.PersonDocumentAffiliation;
035    import org.kuali.rice.kim.bo.ui.PersonDocumentCitizenship;
036    import org.kuali.rice.kim.bo.ui.PersonDocumentEmail;
037    import org.kuali.rice.kim.bo.ui.PersonDocumentEmploymentInfo;
038    import org.kuali.rice.kim.bo.ui.PersonDocumentGroup;
039    import org.kuali.rice.kim.bo.ui.PersonDocumentName;
040    import org.kuali.rice.kim.bo.ui.PersonDocumentPhone;
041    import org.kuali.rice.kim.bo.ui.PersonDocumentPrivacy;
042    import org.kuali.rice.kim.bo.ui.PersonDocumentRole;
043    import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMember;
044    import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMemberQualifier;
045    import org.kuali.rice.kim.impl.identity.principal.PrincipalBo;
046    import org.kuali.rice.kim.impl.type.KimTypeAttributesHelper;
047    import org.kuali.rice.kim.service.KIMServiceLocatorInternal;
048    import org.kuali.rice.kim.service.UiDocumentService;
049    import org.kuali.rice.kns.service.DocumentHelperService;
050    import org.kuali.rice.kns.service.KNSServiceLocator;
051    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
052    import org.kuali.rice.krad.service.SequenceAccessorService;
053    import org.kuali.rice.krad.util.GlobalVariables;
054    
055    import javax.persistence.AssociationOverride;
056    import javax.persistence.AssociationOverrides;
057    import javax.persistence.AttributeOverride;
058    import javax.persistence.AttributeOverrides;
059    import javax.persistence.CascadeType;
060    import javax.persistence.Column;
061    import javax.persistence.Entity;
062    import javax.persistence.FetchType;
063    import javax.persistence.GeneratedValue;
064    import javax.persistence.JoinColumn;
065    import javax.persistence.OneToMany;
066    import javax.persistence.OneToOne;
067    import javax.persistence.Table;
068    import javax.persistence.Transient;
069    import java.util.ArrayList;
070    import java.util.HashMap;
071    import java.util.List;
072    import 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")
089    public 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.getId().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    }