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