001    /*
002    // This software is subject to the terms of the Common Public License
003    // Agreement, available at the following URL:
004    // http://www.opensource.org/licenses/cpl.html.
005    // Copyright (C) 2007-2007 Julian Hyde
006    // All Rights Reserved.
007    // You must accept the terms of that agreement to use this software.
008    */
009    package mondrian.olap;
010    
011    import java.util.List;
012    import java.util.ArrayList;
013    
014    /**
015     * Implementation of {@link Role} which combines the privileges of several
016     * roles and has the superset of their privileges.
017     *
018     * @see mondrian.olap.RoleImpl#union(java.util.List)
019     *
020     * @author jhyde
021     * @version $Id: //open/mondrian/src/main/mondrian/olap/UnionRoleImpl.java#1 $
022     * @since Nov 26, 2007
023     */
024    class UnionRoleImpl implements Role {
025        private final List<Role> roleList;
026    
027        /**
028         * Creates a UnionRoleImpl.
029         *
030         * @param roleList List of constituent roles
031         */
032        UnionRoleImpl(List<Role> roleList) {
033            this.roleList = new ArrayList<Role>(roleList);
034        }
035    
036        public Access getAccess(Schema schema) {
037            Access access = Access.NONE;
038            for (Role role : roleList) {
039                access = max(access, role.getAccess(schema));
040                if (access == Access.ALL) {
041                    break;
042                }
043            }
044            return access;
045        }
046    
047        /**
048         * Returns the larger of two enum values. Useful if the enums are sorted
049         * so that more permissive values come after less permissive values.
050         *
051         * @param t1 First value
052         * @param t2 Second value
053         * @return larger of the two values
054         */
055        private static <T extends Enum<T>> T max(T t1, T t2) {
056            if (t1.ordinal() > t2.ordinal()) {
057                return t1;
058            } else {
059                return t2;
060            }
061        }
062    
063        public Access getAccess(Cube cube) {
064            Access access = Access.NONE;
065            for (Role role : roleList) {
066                access = max(access, role.getAccess(cube));
067                if (access == Access.ALL) {
068                    break;
069                }
070            }
071            return access;
072        }
073    
074        public Access getAccess(Dimension dimension) {
075            Access access = Access.NONE;
076            for (Role role : roleList) {
077                access = max(access, role.getAccess(dimension));
078                if (access == Access.ALL) {
079                    break;
080                }
081            }
082            return access;
083        }
084    
085        public Access getAccess(Hierarchy hierarchy) {
086            Access access = Access.NONE;
087            for (Role role : roleList) {
088                access = max(access, role.getAccess(hierarchy));
089                if (access == Access.ALL) {
090                    break;
091                }
092            }
093            return access;
094        }
095    
096        public HierarchyAccess getAccessDetails(final Hierarchy hierarchy) {
097            List<HierarchyAccess> list = new ArrayList<HierarchyAccess>();
098            for (Role role : roleList) {
099                final HierarchyAccess accessDetails =
100                    role.getAccessDetails(hierarchy);
101                if (accessDetails != null) {
102                    list.add(accessDetails);
103                }
104            }
105            // If none of the roles call out access details, we shouldn't either.
106            if (list.isEmpty()) {
107                return null;
108            }
109            return new UnionHierarchyAccessImpl(hierarchy, list);
110        }
111    
112        public Access getAccess(Level level) {
113            Access access = Access.NONE;
114            for (Role role : roleList) {
115                access = max(access, role.getAccess(level));
116                if (access == Access.ALL) {
117                    break;
118                }
119            }
120            return access;
121        }
122    
123        public Access getAccess(Member member) {
124            assert member != null;
125            HierarchyAccess hierarchyAccess =
126                getAccessDetails(member.getHierarchy());
127            if (hierarchyAccess != null) {
128                return hierarchyAccess.getAccess(member);
129            }
130            return getAccess(member.getDimension());
131        }
132    
133        public Access getAccess(NamedSet set) {
134            Access access = Access.NONE;
135            for (Role role : roleList) {
136                access = max(access, role.getAccess(set));
137                if (access == Access.ALL) {
138                    break;
139                }
140            }
141            return access;
142        }
143    
144        public boolean canAccess(OlapElement olapElement) {
145            for (Role role : roleList) {
146                if (role.canAccess(olapElement)) {
147                    return true;
148                }
149            }
150            return false;
151        }
152    
153        private class UnionHierarchyAccessImpl implements HierarchyAccess {
154            private final List<HierarchyAccess> list;
155    
156            UnionHierarchyAccessImpl(
157                Hierarchy hierarchy,
158                List<HierarchyAccess> list)
159            {
160                Util.discard(hierarchy);
161                this.list = list;
162            }
163    
164            public Access getAccess(Member member) {
165                Access access = Access.NONE;
166                for (Role role : roleList) {
167                    access = max(access, role.getAccess(member));
168                    if (access == Access.ALL) {
169                        break;
170                    }
171                }
172                return access;
173            }
174    
175            public int getTopLevelDepth() {
176                int access = Integer.MAX_VALUE;
177                for (HierarchyAccess hierarchyAccess : list) {
178                    access =
179                        Math.min(
180                            access,
181                            hierarchyAccess.getTopLevelDepth());
182                    if (access == 0) {
183                        break;
184                    }
185                }
186                return access;
187            }
188    
189            public int getBottomLevelDepth() {
190                int access = -1;
191                for (HierarchyAccess hierarchyAccess : list) {
192                    access =
193                        Math.max(
194                            access,
195                            hierarchyAccess.getBottomLevelDepth());
196                }
197                return access;
198            }
199    
200            public RollupPolicy getRollupPolicy() {
201                RollupPolicy rollupPolicy = RollupPolicy.HIDDEN;
202                for (HierarchyAccess hierarchyAccess : list) {
203                    rollupPolicy =
204                        max(
205                            rollupPolicy,
206                            hierarchyAccess.getRollupPolicy());
207                    if (rollupPolicy == RollupPolicy.FULL) {
208                        break;
209                    }
210                }
211                return rollupPolicy;
212            }
213    
214            public boolean hasInaccessibleDescendants(Member member) {
215                for (HierarchyAccess hierarchyAccess : list) {
216                    switch (hierarchyAccess.getAccess(member)) {
217                    case NONE:
218                        continue;
219                    case CUSTOM:
220                        return true;
221                    case ALL:
222                        if (!hierarchyAccess.hasInaccessibleDescendants(member)) {
223                            return false;
224                        }
225                    }
226                }
227                return true;
228            }
229        }
230    }
231    
232    // End UnionRoleImpl.java