001    /**
002     * Copyright 2005-2013 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.impl.jaxb;
017    
018    import java.io.Serializable;
019    import java.util.ArrayList;
020    import java.util.Collections;
021    import java.util.HashSet;
022    import java.util.List;
023    import java.util.Set;
024    
025    import javax.xml.bind.Marshaller;
026    import javax.xml.bind.UnmarshalException;
027    import javax.xml.bind.Unmarshaller;
028    import javax.xml.bind.annotation.XmlAccessType;
029    import javax.xml.bind.annotation.XmlAccessorType;
030    import javax.xml.bind.annotation.XmlElement;
031    import javax.xml.bind.annotation.XmlTransient;
032    import javax.xml.bind.annotation.XmlType;
033    
034    import org.kuali.rice.core.api.criteria.QueryByCriteria;
035    import org.kuali.rice.core.util.jaxb.RiceXmlExportList;
036    import org.kuali.rice.core.util.jaxb.RiceXmlImportList;
037    import org.kuali.rice.core.util.jaxb.RiceXmlListAdditionListener;
038    import org.kuali.rice.core.util.jaxb.RiceXmlListGetterListener;
039    import org.kuali.rice.kim.api.role.RoleMember;
040    import org.kuali.rice.kim.api.role.RoleMemberContract;
041    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
042    
043    import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
044    
045    /**
046     * Base class representing an unmarshalled <roleMembers> element.
047     * Refer to the static inner classes for more information about the specific contexts.
048     * 
049     * @author Kuali Rice Team (rice.collab@kuali.org)
050     */
051    @XmlTransient
052    public abstract class RoleMembersXmlDTO<T extends RoleMemberXmlDTO> implements RiceXmlListAdditionListener<T>, Serializable {
053    
054        private static final long serialVersionUID = 1L;
055    
056        public abstract List<T> getRoleMembers();
057        
058        public abstract void setRoleMembers(List<T> roleMembers);
059        
060        void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
061            setRoleMembers(new RiceXmlImportList<T>(this));
062        }
063        
064        void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
065            setRoleMembers(null);
066        }
067        
068        // =======================================================================================================
069        
070        /**
071         * This class represents a &lt;roleMembers&gt; element that is not a child of a &lt;role&gt; element.
072         * 
073         * @author Kuali Rice Team (rice.collab@kuali.org)
074         */
075        @XmlAccessorType(XmlAccessType.FIELD)
076        @XmlType(name="StandaloneRoleMembersType", propOrder={"roleMembers"})
077        public static class OutsideOfRole extends RoleMembersXmlDTO<RoleMemberXmlDTO.OutsideOfRole> {
078    
079            private static final long serialVersionUID = 1L;
080            
081            @XmlElement(name="roleMember")
082            private List<RoleMemberXmlDTO.OutsideOfRole> roleMembers;
083    
084            /**
085             * @see org.kuali.rice.kim.impl.jaxb.RoleMembersXmlDTO#getRoleMembers()
086             */
087            @Override
088            public List<RoleMemberXmlDTO.OutsideOfRole> getRoleMembers() {
089                return this.roleMembers;
090            }
091    
092            /**
093             * @see org.kuali.rice.kim.impl.jaxb.RoleMembersXmlDTO#setRoleMembers(java.util.List)
094             */
095            @Override
096            public void setRoleMembers(List<RoleMemberXmlDTO.OutsideOfRole> roleMembers) {
097                this.roleMembers = roleMembers;
098            }
099    
100            /**
101             * @see org.kuali.rice.core.util.jaxb.RiceXmlListAdditionListener#newItemAdded(java.lang.Object)
102             */
103            @Override
104            public void newItemAdded(RoleMemberXmlDTO.OutsideOfRole item) {
105                try {
106                    RoleXmlUtil.validateAndPersistNewRoleMember(item);
107                } catch (UnmarshalException e) {
108                    throw new RuntimeException(e);
109                }
110            }
111        }
112        
113        // =======================================================================================================
114        
115        /**
116         * This class represents a &lt;roleMembers&gt; element that is a child of a &lt;role&gt; element.
117         * 
118         * @author Kuali Rice Team (rice.collab@kuali.org)
119         */
120        @XmlAccessorType(XmlAccessType.FIELD)
121        @XmlType(name="RoleMembersType", propOrder={"roleMembers"})
122        public static class WithinRole extends RoleMembersXmlDTO<RoleMemberXmlDTO.WithinRole>
123                implements RiceXmlListGetterListener<RoleMemberXmlDTO.WithinRole,String> {
124    
125            private static final long serialVersionUID = 1L;
126            
127            @XmlElement(name="roleMember")
128            private List<RoleMemberXmlDTO.WithinRole> roleMembers;
129    
130            @XmlTransient
131            private String roleId;
132            
133            @XmlTransient
134            private Set<String> existingRoleMemberIds;
135            
136            public WithinRole() {}
137            
138            public WithinRole(String roleId) {
139                this.roleId = roleId;
140            }
141            
142            /**
143             * @see org.kuali.rice.kim.impl.jaxb.RoleMembersXmlDTO#getRoleMembers()
144             */
145            @Override
146            public List<org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO.WithinRole> getRoleMembers() {
147                return this.roleMembers;
148            }
149    
150            /**
151             * @see org.kuali.rice.kim.impl.jaxb.RoleMembersXmlDTO#setRoleMembers(java.util.List)
152             */
153            @Override
154            public void setRoleMembers(List<org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO.WithinRole> roleMembers) {
155                this.roleMembers = roleMembers;
156            }
157            
158            /**
159             * @return the roleId
160             */
161            public String getRoleId() {
162                return this.roleId;
163            }
164    
165            /**
166             * @see org.kuali.rice.kim.impl.jaxb.RoleMembersXmlDTO#beforeUnmarshal(javax.xml.bind.Unmarshaller, java.lang.Object)
167             */
168            @Override
169            void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
170                if (parent instanceof RoleXmlDTO) {
171                    // Obtain the role ID from the enclosing role, and persist the role if it has not been persisted yet.
172                    RoleXmlDTO parentRole = (RoleXmlDTO) parent;
173                    if (!parentRole.isAlreadyPersisted()) {
174                        RoleXmlUtil.validateAndPersistNewRole(parentRole);
175                    }
176                    roleId = parentRole.getRoleId();
177                }
178                existingRoleMemberIds = new HashSet<String>();
179                super.beforeUnmarshal(unmarshaller, parent);
180            }
181    
182            /**
183             * This overridden method ...
184             * 
185             * @see org.kuali.rice.kim.impl.jaxb.RoleMembersXmlDTO#afterUnmarshal(javax.xml.bind.Unmarshaller, java.lang.Object)
186             */
187            @Override
188            void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
189                super.afterUnmarshal(unmarshaller, parent);
190                if (parent instanceof RoleXmlDTO) {
191                    ((RoleXmlDTO)parent).setExistingRoleMemberIds(existingRoleMemberIds);
192                }
193                existingRoleMemberIds = null;
194            }
195    
196            /**
197             * @see org.kuali.rice.core.util.jaxb.RiceXmlListAdditionListener#newItemAdded(java.lang.Object)
198             */
199            @Override
200            public void newItemAdded(org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO.WithinRole item) {
201                // Persist the role member and add it to the set of role members that should not be removed from the role.
202                try {
203                    existingRoleMemberIds.add(RoleXmlUtil.validateAndPersistNewRoleMember(item));
204                } catch (UnmarshalException e) {
205                    throw new RuntimeException(e);
206                }
207            }
208            
209            void beforeMarshal(Marshaller marshaller) {
210                List<RoleMember> tempMembers = KimApiServiceLocator.getRoleService().findRoleMembers(
211                        QueryByCriteria.Builder.fromPredicates(equal("roleId", roleId))).getResults();
212                if (tempMembers != null && !tempMembers.isEmpty()) {
213                    List<String> roleMemberIds = new ArrayList<String>();
214                    
215                    for (RoleMemberContract tempMember : tempMembers) {
216                        if (tempMember.isActive(null)) {
217                            roleMemberIds.add(tempMember.getId());
218                        }
219                    }
220                    
221                    if (!roleMemberIds.isEmpty()) {
222                        setRoleMembers(new RiceXmlExportList<RoleMemberXmlDTO.WithinRole,String>(roleMemberIds, this));
223                    }
224                }
225            }
226            
227            void afterMarshal(Marshaller marshaller) {
228                setRoleMembers(null);
229            }
230    
231            /**
232             * @see org.kuali.rice.core.util.jaxb.RiceXmlListGetterListener#gettingNextItem(java.lang.Object, int)
233             */
234            @Override
235            public RoleMemberXmlDTO.WithinRole gettingNextItem(String nextItem, int index) {
236                return new RoleMemberXmlDTO.WithinRole(KimApiServiceLocator.getRoleService().findRoleMembers(QueryByCriteria.Builder.fromPredicates(equal("roleMemberId", nextItem))).getResults().get(0), false);
237            }
238        }
239    }