KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > olap > Role


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/Role.java#15 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2002-2002 Kana Software, Inc.
7 // Copyright (C) 2002-2006 Julian Hyde and others
8 // All Rights Reserved.
9 // You must accept the terms of that agreement to use this software.
10 //
11 // jhyde, Oct 5, 2002
12 */

13
14 package mondrian.olap;
15
16 import java.util.*;
17
18 /**
19  * A <code>Role</code> is a collection of access rights to cubes, permissions,
20  * and so forth.
21  *
22  * <p>At present, the only way to create a role is programmatically. You then
23  * add appropriate permissions, and associate the role with a connection.
24  * Queries executed for the duration of the connection will b.
25  *
26  * <p>Mondrian does not have any notion of a 'user'. It is the client
27  * application's responsibility to create a role appropriate for the user who
28  * is establishing the connection.
29  *
30  * @author jhyde
31  * @since Oct 5, 2002
32  * @version $Id: //open/mondrian/src/main/mondrian/olap/Role.java#15 $
33  */

34 public class Role {
35     private boolean mutable = true;
36     private final Map<Schema, Access> schemaGrants =
37         new HashMap<Schema, Access>();
38     private final Map<Cube, Access> cubeGrants =
39         new HashMap<Cube, Access>();
40     private final Map<Dimension, Access> dimensionGrants =
41         new HashMap<Dimension, Access>();
42     private final Map<Hierarchy, HierarchyAccess> hierarchyGrants =
43         new HashMap<Hierarchy, HierarchyAccess>();
44
45     /**
46      * Creates a role with no permissions.
47      */

48     public Role() {}
49
50     protected Role clone() {
51         Role role = new Role();
52         role.mutable = mutable;
53         role.schemaGrants.putAll(schemaGrants);
54         role.cubeGrants.putAll(cubeGrants);
55         role.dimensionGrants.putAll(dimensionGrants);
56         for (Map.Entry<Hierarchy, HierarchyAccess> entry :
57             hierarchyGrants.entrySet()) {
58             role.hierarchyGrants.put(
59                 entry.getKey(),
60                 entry.getValue().clone());
61         }
62         return role;
63     }
64
65     /**
66      * Returns a copy of this <code>Role</code> which can be modified.
67      */

68     public Role makeMutableClone() {
69         Role role = clone();
70         role.mutable = true;
71         return role;
72     }
73
74     /**
75      * Prevents any further modifications.
76      * @post !isMutable()
77      */

78     public void makeImmutable() {
79         mutable = false;
80     }
81     /**
82      * Returns whether modifications are possible.
83      */

84     public boolean isMutable() {
85         return mutable;
86     }
87     /**
88      * Defines access to all cubes and dimensions in a schema.
89      *
90      * @param schema Schema whose access to grant/deny.
91      * @param access An {@link Access access code}
92      *
93      * @pre schema != null
94      * @pre access == Access.ALL || access == Access.NONE || access == Access.ALL_DIMENSIONS
95      * @pre isMutable()
96      */

97     public void grant(Schema schema, Access access) {
98         assert schema != null;
99         assert access == Access.ALL || access == Access.NONE || access == Access.ALL_DIMENSIONS;
100         assert isMutable();
101         schemaGrants.put(schema, access);
102     }
103
104     /**
105      * Returns the access this role has to a given schema.
106      *
107      * @pre schema != null
108      * @post return == Access.ALL || return == Access.NONE || return == Access.ALL_DIMENSIONS
109      */

110     public Access getAccess(Schema schema) {
111         assert schema != null;
112         return toAccess(schemaGrants.get(schema));
113     }
114
115     private static Access toAccess(Access access) {
116         return access == null ? Access.NONE : access;
117     }
118
119     /**
120      * Defines access to a cube.
121      *
122      * @param cube Cube whose access to grant/deny.
123      * @param access An {@link Access access code}
124      *
125      * @pre cube != null
126      * @pre access == Access.ALL || access == Access.NONE
127      * @pre isMutable()
128      */

129     public void grant(Cube cube, Access access) {
130         Util.assertPrecondition(cube != null, "cube != null");
131         assert access == Access.ALL || access == Access.NONE;
132         Util.assertPrecondition(isMutable(), "isMutable()");
133         cubeGrants.put(cube, access);
134     }
135
136     /**
137      * Returns the access this role has to a given cube.
138      *
139      * @pre cube != null
140      * @post return == Access.ALL || return == Access.NONE
141      */

142     public Access getAccess(Cube cube) {
143         assert cube != null;
144         Access access = cubeGrants.get(cube);
145         if (access == null) {
146             access = schemaGrants.get(cube.getSchema());
147         }
148         return toAccess(access);
149     }
150
151     /**
152      * Represents the access that a role has to a particular hierarchy.
153      */

154     public static class HierarchyAccess {
155         private final Hierarchy hierarchy;
156         private final Level topLevel;
157         private final Access access;
158         private final Level bottomLevel;
159         private final Map<Member, Access> memberGrants =
160             new HashMap<Member, Access>();
161
162         /**
163          * Creates a <code>HierarchyAccess</code>
164          */

165         HierarchyAccess(
166                 Hierarchy hierarchy,
167                 Access access,
168                 Level topLevel,
169                 Level bottomLevel) {
170             assert access != null;
171             this.hierarchy = hierarchy;
172             this.access = access;
173             this.topLevel = topLevel;
174             this.bottomLevel = bottomLevel;
175         }
176
177         public HierarchyAccess clone() {
178             HierarchyAccess hierarchyAccess = new HierarchyAccess(
179                     hierarchy, access, topLevel, bottomLevel);
180             hierarchyAccess.memberGrants.putAll(memberGrants);
181             return hierarchyAccess;
182         }
183
184         void grant(Member member, Access access) {
185             Util.assertTrue(member.getHierarchy() == hierarchy);
186             // Remove any existing grants to descendants of "member"
187
for (Iterator<Member> memberIter =
188                     memberGrants.keySet().iterator(); memberIter.hasNext();) {
189                 Member m = memberIter.next();
190                 if (m.isChildOrEqualTo(member)) {
191                     memberIter.remove();
192                 }
193             }
194
195             memberGrants.put(member, access);
196
197             if (access == Access.NONE) {
198                 // If an ancestor of this member has any children with 'All'
199
// access, set them to Custom.
200
loop:
201                 for (Member m = member.getParentMember();
202                      m != null;
203                      m = m.getParentMember()) {
204                     final Access memberAccess = memberGrants.get(m);
205                     if (memberAccess == null) {
206                         if (childGrantsExist(m)) {
207                             memberGrants.put(m, Access.CUSTOM);
208                         } else {
209                             break;
210                         }
211                     } else if (memberAccess == Access.CUSTOM) {
212                         // Ancestor does not inherit access, but used to have
213
// at least one child with access. See if it still
214
// does...
215
if (childGrantsExist(m)) {
216                             memberGrants.put(m, Access.CUSTOM);
217                         } else {
218                             break;
219                         }
220                     } else if (memberAccess == Access.NONE) {
221                         // Ancestor is explicitly marked having no access.
222
// Leave it that way.
223
break;
224                     } else if (memberAccess == Access.ALL) {
225                         // Ancestor is explicitly marked having all access.
226
// Leave it that way.
227
break;
228                     }
229                 }
230
231             } else {
232
233                 // Create 'custom' access for any ancestors of 'member' which
234
// do not have explicit access but which have at least one
235
// child visible.
236
for (Member m = member.getParentMember();
237                      m != null;
238                      m = m.getParentMember()) {
239                     switch (toAccess(memberGrants.get(m))) {
240                     case NONE:
241                         memberGrants.put(m, Access.CUSTOM);
242                         break;
243                     default:
244                         // Existing access (All or Custom) is OK.
245
break;
246                     }
247                 }
248             }
249         }
250
251         private boolean childGrantsExist(Member parent) {
252             for (final Member member : memberGrants.keySet()) {
253                 if (member.getParentMember() == parent) {
254                     final Access access = toAccess(memberGrants.get(member));
255                     if (access != Access.NONE) {
256                         return true;
257                     }
258                 }
259             }
260             return false;
261         }
262
263         public Access getAccess(Member member) {
264             if (this.access != Access.CUSTOM) {
265                 return this.access;
266             }
267             if (topLevel != null &&
268                     member.getLevel().getDepth() < topLevel.getDepth()) {
269                 // no access
270
return Access.NONE;
271             } else if (bottomLevel != null &&
272                     member.getLevel().getDepth() > bottomLevel.getDepth()) {
273                 // no access
274
return Access.NONE;
275             } else {
276                 for (Member m = member; m != null; m = m.getParentMember()) {
277                     final Access memberAccess = memberGrants.get(m);
278                     if (memberAccess == null) {
279                         continue;
280                     }
281                     if (memberAccess == Access.CUSTOM &&
282                             m != member) {
283                         // If member's ancestor has custom access, that
284
// means that member has no access.
285
return Access.NONE;
286                     }
287                     return memberAccess;
288                 }
289                 return Access.NONE;
290             }
291         }
292
293         public Hierarchy getHierarchy() {
294             return hierarchy;
295         }
296
297         public Level getTopLevel() {
298             return topLevel;
299         }
300
301         public Level getBottomLevel() {
302             return bottomLevel;
303         }
304
305         public Map<Member, Access> getMemberGrants() {
306             return Collections.unmodifiableMap(memberGrants);
307         }
308     }
309
310     /**
311      * Defines access to a dimension.
312      *
313      * @param dimension Hierarchy whose access to grant/deny.
314      * @param access An {@link Access access code}
315      *
316      * @pre dimension != null
317      * @pre access == Access.ALL || access == Access.NONE
318      * @pre isMutable()
319      */

320     public void grant(Dimension dimension, Access access) {
321         assert dimension != null;
322         assert access == Access.ALL || access == Access.NONE;
323         Util.assertPrecondition(isMutable(), "isMutable()");
324         dimensionGrants.put(dimension, access);
325     }
326
327     /**
328      * Returns the access this role has to a given dimension.
329      *
330      * @pre dimension != null
331      * @post Access.instance().isValid(return)
332      */

333     public Access getAccess(Dimension dimension) {
334         assert dimension != null;
335         Access access = dimensionGrants.get(dimension);
336         if (access != null) {
337             return toAccess(access);
338         }
339         // If the role has access to a cube this dimension is part of, that's
340
// good enough.
341
for (Map.Entry<Cube,Access> cubeGrant : cubeGrants.entrySet()) {
342             access = toAccess(cubeGrant.getValue());
343             if (access == Access.NONE) {
344                 continue;
345             }
346             final Dimension[] dimensions = cubeGrant.getKey().getDimensions();
347             for (Dimension dimension1 : dimensions) {
348                 if (dimension1 == dimension) {
349                     return access;
350                 }
351             }
352         }
353         // Check access at the schema level.
354
switch (getAccess(dimension.getSchema())) {
355         case ALL:
356         case ALL_DIMENSIONS:
357             return Access.ALL;
358         default:
359             return Access.NONE;
360         }
361     }
362
363     /**
364      * Defines access to a hierarchy.
365      *
366      * @param hierarchy Hierarchy whose access to grant/deny.
367      * @param access An {@link Access access code}
368      * @param topLevel Top-most level which can be accessed, or null if the
369      * highest level. May only be specified if <code>access</code> is
370      * {@link mondrian.olap.Access#CUSTOM}.
371      * @param bottomLevel Bottom-most level which can be accessed, or null if
372      * the lowest level. May only be specified if <code>access</code> is
373      * {@link mondrian.olap.Access#CUSTOM}.
374      *
375      * @pre hierarchy != null
376      * @pre Access.instance().isValid(access)
377      * @pre (access == Access.CUSTOM) || (topLevel == null && bottomLevel == null)
378      * @pre topLevel == null || topLevel.getHierarchy() == hierarchy
379      * @pre bottomLevel == null || bottomLevel.getHierarchy() == hierarchy
380      * @pre isMutable()
381      */

382     public void grant(
383             Hierarchy hierarchy,
384             Access access,
385             Level topLevel,
386             Level bottomLevel) {
387         Util.assertPrecondition(hierarchy != null, "hierarchy != null");
388         assert access != null;
389         Util.assertPrecondition((access == Access.CUSTOM) || (topLevel == null && bottomLevel == null), "access == Access.CUSTOM) || (topLevel == null && bottomLevel == null)");
390         Util.assertPrecondition(topLevel == null || topLevel.getHierarchy() == hierarchy, "topLevel == null || topLevel.getHierarchy() == hierarchy");
391         Util.assertPrecondition(bottomLevel == null || bottomLevel.getHierarchy() == hierarchy, "bottomLevel == null || bottomLevel.getHierarchy() == hierarchy");
392         Util.assertPrecondition(isMutable(), "isMutable()");
393         hierarchyGrants.put(
394             hierarchy,
395             new HierarchyAccess(hierarchy, access, topLevel, bottomLevel));
396     }
397
398     /**
399      * Returns the access this role has to a given hierarchy.
400      *
401      * @pre hierarchy != null
402      * @post return == Access.NONE || return == Access.ALL || return == Access.CUSTOM
403      */

404     public Access getAccess(Hierarchy hierarchy) {
405         assert hierarchy != null;
406         HierarchyAccess access = hierarchyGrants.get(hierarchy);
407         if (access != null) {
408             return access.access;
409         }
410         return getAccess(hierarchy.getDimension());
411     }
412
413     /**
414      * Returns the details of this hierarchy's access, or null if the hierarchy
415      * has not been given explicit access.
416      *
417      * @pre hierarchy != null
418      */

419     public HierarchyAccess getAccessDetails(Hierarchy hierarchy) {
420         Util.assertPrecondition(hierarchy != null, "hierarchy != null");
421         return hierarchyGrants.get(hierarchy);
422     }
423
424     /**
425      * Returns the access this role has to a given level.
426      *
427      * @pre level != null
428      * @post Access.instance().isValid(return)
429      */

430     public Access getAccess(Level level) {
431         assert level != null;
432         HierarchyAccess access = hierarchyGrants.get(level.getHierarchy());
433         if (access != null) {
434             if (access.topLevel != null &&
435                     level.getDepth() < access.topLevel.getDepth()) {
436                 return Access.NONE;
437             }
438             if (access.bottomLevel != null &&
439                     level.getDepth() > access.bottomLevel.getDepth()) {
440                 return Access.NONE;
441             }
442             return access.access;
443         }
444         return getAccess(level.getDimension());
445     }
446
447     /**
448      * Defines access to a member in a hierarchy.
449      *
450      * <p>Notes:<ol>
451      * <li>The order of grants matters. If you grant/deny access to a
452      * member, previous grants/denials to its descendants are ignored.</li>
453      * <li>Member grants do not supersde top/bottom levels set using
454      * {@link #grant(Hierarchy,Access,Level,Level)}.
455      * <li>If you have access to a member, then you can see its ancestors
456      * <em>even those explicitly denied</em>, up to the top level.
457      * </ol>
458      *
459      * @pre member != null
460      * @pre Access.instance().isValid(access)
461      * @pre isMutable()
462      * @pre getAccess(member.getHierarchy()) == Access.CUSTOM
463      */

464     public void grant(Member member, Access access) {
465         Util.assertPrecondition(member != null, "member != null");
466         assert Util.isValid(Access.class, access);
467         assert isMutable();
468         assert getAccess(member.getHierarchy()) == Access.CUSTOM;
469         HierarchyAccess hierarchyAccess = hierarchyGrants.get(member.getHierarchy());
470         assert hierarchyAccess != null;
471         assert hierarchyAccess.access == Access.CUSTOM;
472         hierarchyAccess.grant(member, access);
473     }
474
475     /**
476      * Returns the access this role has to a given member.
477      *
478      * @pre member != null
479      * @pre isMutable()
480      * @post return == Access.NONE || return == Access.ALL || return == Access.CUSTOM
481      */

482     public Access getAccess(Member member) {
483         assert member != null;
484         HierarchyAccess hierarchyAccess =
485             hierarchyGrants.get(member.getHierarchy());
486         if (hierarchyAccess != null) {
487             return hierarchyAccess.getAccess(member);
488         }
489         return getAccess(member.getDimension());
490     }
491
492     /**
493      * Returns the access this role has to a given named set.
494      *
495      * @pre set != null
496      * @pre isMutable()
497      * @post return == Access.NONE || return == Access.ALL
498      */

499     public Access getAccess(NamedSet set) {
500         Util.assertPrecondition(set != null, "set != null");
501         return Access.ALL;
502     }
503
504     /**
505      * Returns whether this role is allowed to see a given element.
506      * @pre olapElement != null
507      */

508     public boolean canAccess(OlapElement olapElement) {
509         Util.assertPrecondition(olapElement != null, "olapElement != null");
510         if (olapElement instanceof Cube) {
511             return getAccess((Cube) olapElement) != Access.NONE;
512         } else if (olapElement instanceof Dimension) {
513             return getAccess((Dimension) olapElement) != Access.NONE;
514         } else if (olapElement instanceof Hierarchy) {
515             return getAccess((Hierarchy) olapElement) != Access.NONE;
516         } else if (olapElement instanceof Level) {
517             return getAccess((Level) olapElement) != Access.NONE;
518         } else if (olapElement instanceof Member) {
519             return getAccess((Member) olapElement) != Access.NONE;
520         } else if (olapElement instanceof NamedSet) {
521             return getAccess((NamedSet) olapElement) != Access.NONE;
522         } else {
523             return false;
524         }
525     }
526 }
527
528 // End Role.java
529
Popular Tags