001/*
002 * Copyright 2011 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/ecl1.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.impl.jaxb;
017
018import java.io.Serializable;
019import java.util.ArrayList;
020import java.util.List;
021
022import javax.xml.bind.Marshaller;
023import javax.xml.bind.UnmarshalException;
024import javax.xml.bind.Unmarshaller;
025import javax.xml.bind.annotation.XmlAccessType;
026import javax.xml.bind.annotation.XmlAccessorType;
027import javax.xml.bind.annotation.XmlElement;
028import javax.xml.bind.annotation.XmlTransient;
029import javax.xml.bind.annotation.XmlType;
030
031import org.kuali.rice.core.util.jaxb.RiceXmlExportList;
032import org.kuali.rice.core.util.jaxb.RiceXmlImportList;
033import org.kuali.rice.core.util.jaxb.RiceXmlListAdditionListener;
034import org.kuali.rice.core.util.jaxb.RiceXmlListGetterListener;
035import org.kuali.rice.kim.api.permission.PermissionContract;
036import org.kuali.rice.kim.api.services.KimApiServiceLocator;
037
038/**
039 * Base class representing an unmarshalled <rolePermissions> element.
040 * Refer to the static inner classes for more information about the specific contexts.
041 * 
042 * TODO: Alter the role/permission service APIs so that finding all the permissions assigned to a role is possible; the
043 * current lack of such an API method prevents role permissions from being exported.
044 * 
045 * @author Kuali Rice Team (rice.collab@kuali.org)
046 */
047@XmlTransient
048public abstract class RolePermissionsXmlDTO<T extends RolePermissionXmlDTO> implements RiceXmlListAdditionListener<T>, Serializable {
049    
050    private static final long serialVersionUID = 1L;
051
052    public abstract List<T> getRolePermissions();
053    
054    public abstract void setRolePermissions(List<T> rolePermissions);
055    
056    void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
057        setRolePermissions(new RiceXmlImportList<T>(this));
058    }
059    
060    void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
061        setRolePermissions(null);
062    }
063    
064    // =======================================================================================================
065    
066    /**
067     * This class represents a &lt;rolePermissions&gt; element that is not a child of a &lt;role&gt; element.
068     * 
069     * @author Kuali Rice Team (rice.collab@kuali.org)
070     */
071    @XmlAccessorType(XmlAccessType.FIELD)
072    @XmlType(name="StandaloneRolePermissionsType", propOrder={"rolePermissions"})
073    public static class OutsideOfRole extends RolePermissionsXmlDTO<RolePermissionXmlDTO.OutsideOfRole> {
074        
075        private static final long serialVersionUID = 1L;
076        
077        @XmlElement(name="rolePermission")
078        private List<RolePermissionXmlDTO.OutsideOfRole> rolePermissions;
079        
080        public List<RolePermissionXmlDTO.OutsideOfRole> getRolePermissions() {
081            return rolePermissions;
082        }
083
084        public void setRolePermissions(List<RolePermissionXmlDTO.OutsideOfRole> rolePermissions) {
085            this.rolePermissions = rolePermissions;
086        }
087        
088        public void newItemAdded(RolePermissionXmlDTO.OutsideOfRole item) {
089            try {
090                RoleXmlUtil.validateAndPersistNewRolePermission(item);
091            } catch (UnmarshalException e) {
092                throw new RuntimeException(e);
093            }
094        }
095        
096    }
097    
098    // =======================================================================================================
099    
100    /**
101     * This class represents a &lt;rolePermissions&gt; element that is a child of a &lt;role&gt; element.
102     * 
103     * @author Kuali Rice Team (rice.collab@kuali.org)
104     */
105    @XmlAccessorType(XmlAccessType.FIELD)
106    @XmlType(name="RolePermissionsType", propOrder={"rolePermissions"})
107    public static class WithinRole extends RolePermissionsXmlDTO<RolePermissionXmlDTO.WithinRole>
108            implements RiceXmlListGetterListener<RolePermissionXmlDTO.WithinRole,String> {
109        
110        private static final long serialVersionUID = 1L;
111
112        @XmlElement(name="rolePermission")
113        private List<RolePermissionXmlDTO.WithinRole> rolePermissions;
114        
115        @XmlTransient
116        private String roleId;
117        
118        public WithinRole() {}
119        
120        public WithinRole(String roleId) {
121            this.roleId = roleId;
122        }
123        
124        public List<RolePermissionXmlDTO.WithinRole> getRolePermissions() {
125            return rolePermissions;
126        }
127
128        public void setRolePermissions(List<RolePermissionXmlDTO.WithinRole> rolePermissions) {
129            this.rolePermissions = rolePermissions;
130        }
131        
132        public String getRoleId() {
133            return roleId;
134        }
135        
136        @Override
137        void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) throws UnmarshalException {
138            if (parent instanceof RoleXmlDTO) {
139                // Obtain the role ID from the enclosing role, and persist the role if it has not been persisted yet.
140                RoleXmlDTO parentRole = (RoleXmlDTO) parent;
141                if (!parentRole.isAlreadyPersisted()) {
142                    RoleXmlUtil.validateAndPersistNewRole(parentRole);
143                }
144                roleId = parentRole.getRoleId();
145            }
146            super.beforeUnmarshal(unmarshaller, parent);
147        }
148        
149        public void newItemAdded(RolePermissionXmlDTO.WithinRole item) {
150            try {
151                RoleXmlUtil.validateAndPersistNewRolePermission(item);
152            } catch (UnmarshalException e) {
153                throw new RuntimeException(e);
154            }
155        }
156        
157        void beforeMarshal(Marshaller marshaller) {
158            // TODO: Use new API method once it becomes available!!!!
159            List<String> permissionIds = new ArrayList<String>();// KIMServiceLocator.getPermissionService().getRoleIdsForPermission(permissionId);
160            if (permissionIds != null && !permissionIds.isEmpty()) {
161                setRolePermissions(new RiceXmlExportList<RolePermissionXmlDTO.WithinRole,String>(permissionIds, this));
162            }
163        }
164        
165        void afterMarshal(Marshaller marshaller) {
166            setRolePermissions(null);
167        }
168
169        public RolePermissionXmlDTO.WithinRole gettingNextItem(String nextItem, int index) {
170            PermissionContract permission = KimApiServiceLocator.getPermissionService().getPermission(nextItem);
171            if (permission == null) {
172                throw new RuntimeException("Cannot find permission with ID \"" + nextItem + "\"");
173            }
174            return new RolePermissionXmlDTO.WithinRole(permission, false);
175        }
176    }
177}