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