001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/CubeAccess.java#14 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 1999-2002 Kana Software, Inc.
007    // Copyright (C) 2001-2008 Julian Hyde and others
008    // All Rights Reserved.
009    // You must accept the terms of that agreement to use this software.
010    //
011    // lkrivopaltsev, 01 November, 1999
012    */
013    
014    package mondrian.olap;
015    import mondrian.resource.MondrianResource;
016    
017    import java.util.List;
018    import java.util.ArrayList;
019    
020    /**
021     * This class implements object of type GrantCube to apply permissions
022     * on user's MDX query
023     */
024    public class CubeAccess {
025    
026        private boolean hasRestrictions;
027        /** array of hierarchies with no access */
028        private Hierarchy[] noAccessHierarchies;
029        /** array of members which have limited access */
030        private Member[]  limitedMembers;
031        private final List<Hierarchy> hierarchyList = new ArrayList<Hierarchy>();
032        private final List<Member> memberList = new ArrayList<Member>();
033        private final Cube mdxCube;
034    
035        /**
036         * Creates a CubeAccess object.
037         *
038         * <p>User's code should be responsible for
039         * filling cubeAccess with restricted hierarchies and restricted
040         * members by calling addSlicer(). Do NOT forget to call
041         * {@link #normalizeCubeAccess()} after you done filling cubeAccess.
042         */
043        public CubeAccess(Cube mdxCube) {
044            this.mdxCube = mdxCube;
045            noAccessHierarchies = null;
046            limitedMembers = null;
047            hasRestrictions = false;
048        }
049    
050        public boolean hasRestrictions() {
051            return hasRestrictions;
052        }
053    
054        public Hierarchy[] getNoAccessHierarchies() {
055            return noAccessHierarchies;
056        }
057    
058        public Member[] getLimitedMembers() {
059            return limitedMembers;
060        }
061    
062        public List<Hierarchy> getNoAccessHierarchyList() {
063            return hierarchyList;
064        }
065    
066        public List<Member> getLimitedMemberList() {
067            return memberList;
068        }
069    
070        public boolean isHierarchyAllowed(Hierarchy mdxHierarchy) {
071            String hierName = mdxHierarchy.getUniqueName();
072            if (noAccessHierarchies == null || hierName == null) {
073                return true;
074            }
075            for (Hierarchy noAccessHierarchy : noAccessHierarchies) {
076                if (hierName.equalsIgnoreCase(noAccessHierarchy.getUniqueName())) {
077                    return false;
078                }
079            }
080            return true;
081        }
082    
083        public Member getLimitedMemberForHierarchy(Hierarchy mdxHierarchy) {
084            String hierName = mdxHierarchy.getUniqueName();
085            if (limitedMembers == null || hierName == null) {
086                return null;
087            }
088            for (Member limitedMember : limitedMembers) {
089                Hierarchy limitedHierarchy = limitedMember.getHierarchy();
090                if (hierName.equalsIgnoreCase(limitedHierarchy.getUniqueName())) {
091                    return limitedMember;
092                }
093            }
094            return null;
095        }
096    
097        /**
098         * Adds  restricted hierarchy or limited member based on bMember
099         */
100        public void addGrantCubeSlicer(
101            String sHierarchy,
102            String sMember,
103            boolean bMember) {
104            if (bMember) {
105                boolean fail = false;
106                List<Id.Segment> sMembers = Util.parseIdentifier(sMember);
107                SchemaReader schemaReader = mdxCube.getSchemaReader(null);
108                Member member = schemaReader.getMemberByUniqueName(sMembers, fail);
109                if (member == null) {
110                    throw MondrianResource.instance().MdxCubeSlicerMemberError.ex(
111                        sMember, sHierarchy, mdxCube.getUniqueName());
112                }
113                // there should be only slicer per hierarchy; ignore the rest
114                if (getLimitedMemberForHierarchy(member.getHierarchy()) == null) {
115                    memberList.add(member);
116                }
117            } else {
118                boolean fail = false;
119                Hierarchy hierarchy = mdxCube.lookupHierarchy(new Id.Segment(
120                        sHierarchy, Id.Quoting.UNQUOTED), fail);
121                if (hierarchy == null) {
122                    throw MondrianResource.instance().MdxCubeSlicerHierarchyError
123                        .ex(sHierarchy, mdxCube.getUniqueName());
124                }
125                hierarchyList.add(hierarchy);
126            }
127        }
128    
129        /**
130         * Initializes internal arrays of restricted hierarchies and limited
131         * members. It has to be called  after all 'addSlicer()' calls.
132         */
133        public void normalizeCubeAccess() {
134            if (memberList.size() > 0) {
135                limitedMembers = memberList.toArray(new Member[memberList.size()]);
136                hasRestrictions = true;
137            }
138            if (hierarchyList.size() > 0) {
139                noAccessHierarchies =
140                    hierarchyList.toArray(
141                        new Hierarchy[hierarchyList.size()]);
142                hasRestrictions = true;
143            }
144        }
145    
146        public boolean equals(Object object) {
147            if (!(object instanceof CubeAccess)) {
148               return false;
149            }
150            CubeAccess cubeAccess = (CubeAccess) object;
151            List<Hierarchy> hierarchyList = cubeAccess.getNoAccessHierarchyList();
152            List<Member> limitedMemberList = cubeAccess.getLimitedMemberList();
153    
154            if ((this.hierarchyList.size() != hierarchyList.size()) ||
155                (this.memberList.size() != limitedMemberList.size())) {
156                return false;
157            }
158            for (Hierarchy o : hierarchyList) {
159                if (!this.hierarchyList.contains(o)) {
160                    return false;
161                }
162            }
163            for (Member member : limitedMemberList) {
164                if (!this.memberList.contains(member)) {
165                    return false;
166                }
167            }
168            return true;
169        }
170    
171        public int hashCode() {
172            int h = mdxCube.hashCode();
173            h = Util.hash(h, hierarchyList);
174            h = Util.hash(h, memberList);
175            h = Util.hashArray(h, noAccessHierarchies);
176            h = Util.hashArray(h, limitedMembers);
177            return h;
178        }
179    }
180    
181    // End CubeAccess.java