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