001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 1999-2005 Julian Hyde
008// Copyright (C) 2005-2012 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.olap;
012
013import mondrian.resource.MondrianResource;
014
015import java.util.ArrayList;
016import java.util.List;
017
018/**
019 * This class implements object of type GrantCube to apply permissions
020 * on user's MDX query
021 *
022 * @author lkrivopaltsev, 01 November, 1999
023 */
024public 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    {
105        if (bMember) {
106            boolean fail = false;
107            List<Id.Segment> sMembers = Util.parseIdentifier(sMember);
108            SchemaReader schemaReader = mdxCube.getSchemaReader(null);
109            Member member = schemaReader.getMemberByUniqueName(sMembers, fail);
110            if (member == null) {
111                throw MondrianResource.instance().MdxCubeSlicerMemberError.ex(
112                    sMember, sHierarchy, mdxCube.getUniqueName());
113            }
114            // there should be only slicer per hierarchy; ignore the rest
115            if (getLimitedMemberForHierarchy(member.getHierarchy()) == null) {
116                memberList.add(member);
117            }
118        } else {
119            boolean fail = false;
120            Hierarchy hierarchy =
121                mdxCube.lookupHierarchy(
122                    new Id.NameSegment(sHierarchy),
123                    fail);
124            if (hierarchy == null) {
125                throw MondrianResource.instance().MdxCubeSlicerHierarchyError
126                    .ex(sHierarchy, mdxCube.getUniqueName());
127            }
128            hierarchyList.add(hierarchy);
129        }
130    }
131
132    /**
133     * Initializes internal arrays of restricted hierarchies and limited
134     * members. It has to be called  after all 'addSlicer()' calls.
135     */
136    public void normalizeCubeAccess() {
137        if (memberList.size() > 0) {
138            limitedMembers = memberList.toArray(new Member[memberList.size()]);
139            hasRestrictions = true;
140        }
141        if (hierarchyList.size() > 0) {
142            noAccessHierarchies =
143                hierarchyList.toArray(
144                    new Hierarchy[hierarchyList.size()]);
145            hasRestrictions = true;
146        }
147    }
148
149    public boolean equals(Object object) {
150        if (!(object instanceof CubeAccess)) {
151            return false;
152        }
153        CubeAccess cubeAccess = (CubeAccess) object;
154        List<Hierarchy> hierarchyList = cubeAccess.getNoAccessHierarchyList();
155        List<Member> limitedMemberList = cubeAccess.getLimitedMemberList();
156
157        if ((this.hierarchyList.size() != hierarchyList.size())
158            || (this.memberList.size() != limitedMemberList.size()))
159        {
160            return false;
161        }
162        for (Hierarchy o : hierarchyList) {
163            if (!this.hierarchyList.contains(o)) {
164                return false;
165            }
166        }
167        for (Member member : limitedMemberList) {
168            if (!this.memberList.contains(member)) {
169                return false;
170            }
171        }
172        return true;
173    }
174
175    public int hashCode() {
176        int h = mdxCube.hashCode();
177        h = Util.hash(h, hierarchyList);
178        h = Util.hash(h, memberList);
179        h = Util.hashArray(h, noAccessHierarchies);
180        h = Util.hashArray(h, limitedMembers);
181        return h;
182    }
183}
184
185// End CubeAccess.java