001    /*
002    // $Id: //open/mondrian/src/main/mondrian/rolap/CacheMemberReader.java#31 $
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) 2001-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    // jhyde, 21 December, 2001
012    */
013    
014    package mondrian.rolap;
015    import java.util.ArrayList;
016    import java.util.HashMap;
017    import java.util.List;
018    import java.util.Map;
019    
020    import mondrian.olap.*;
021    import mondrian.rolap.TupleReader.MemberBuilder;
022    import mondrian.rolap.sql.TupleConstraint;
023    import mondrian.rolap.sql.MemberChildrenConstraint;
024    
025    /**
026     * <code>CacheMemberReader</code> implements {@link MemberReader} by reading
027     * from a pre-populated array of {@link mondrian.olap.Member}s.
028     * <p>Note: CacheMemberReader can not handle ragged hierarchies. (HR
029     * Tests fail if {@link SmartMemberReader} is replaced with
030     * CacheMemberReader).
031     *
032     * @author jhyde
033     * @since 21 December, 2001
034     * @version $Id: //open/mondrian/src/main/mondrian/rolap/CacheMemberReader.java#31 $
035     */
036    class CacheMemberReader implements MemberReader, MemberCache {
037        private final MemberSource source;
038        private final List<RolapMember> members;
039        /** Maps a {@link MemberKey} to a {@link RolapMember}. */
040        private final Map<Object, RolapMember> mapKeyToMember;
041    
042        CacheMemberReader(MemberSource source) {
043            this.source = source;
044            if (false) {
045                // we don't want the reader to write back to our cache
046                Util.discard(source.setCache(this));
047            }
048            this.mapKeyToMember = new HashMap<Object, RolapMember>();
049            this.members = source.getMembers();
050            for (int i = 0; i < members.size(); i++) {
051                members.get(i).setOrdinal(i);
052            }
053        }
054    
055        // implement MemberReader
056        public RolapHierarchy getHierarchy() {
057            return source.getHierarchy();
058        }
059    
060        public boolean setCache(MemberCache cache) {
061            // we do not support cache writeback -- we must be masters of our
062            // own cache
063            return false;
064        }
065    
066        public RolapMember substitute(RolapMember member) {
067            return member;
068        }
069    
070        public RolapMember desubstitute(RolapMember member) {
071            return member;
072        }
073    
074        // implement MemberReader
075        public List<RolapMember> getMembers() {
076            return members;
077        }
078    
079        // implement MemberCache
080        public Object makeKey(RolapMember parent, Object key) {
081            return new MemberKey(parent, key);
082        }
083    
084        // implement MemberCache
085        public RolapMember getMember(Object key) {
086            return mapKeyToMember.get(key);
087        }
088        public RolapMember getMember(Object key, boolean mustCheckCacheStatus) {
089            return mapKeyToMember.get(key);
090        }
091    
092        // implement MemberCache
093        public Object putMember(Object key, RolapMember value) {
094            return mapKeyToMember.put(key, value);
095        }
096    
097        // don't need to implement this MemberCache method because we're never
098        // used in a context where it is needed
099        public void putChildren(
100            RolapMember member,
101            MemberChildrenConstraint constraint,
102            List<RolapMember> children)
103        {
104            throw new UnsupportedOperationException();
105        }
106    
107        // this cache is immutable
108        public boolean isMutable()
109        {
110            return false;
111        }
112    
113        public RolapMember removeMember(Object key)
114        {
115            throw new UnsupportedOperationException();
116        }
117    
118        public RolapMember removeMemberAndDescendants(Object key)
119        {
120            throw new UnsupportedOperationException();
121        }
122    
123        // don't need to implement this MemberCache method because we're never
124        // used in a context where it is needed
125        public List<RolapMember> getChildrenFromCache(
126            RolapMember member,
127            MemberChildrenConstraint constraint)
128        {
129            return null;
130        }
131    
132        // don't need to implement this MemberCache method because we're never
133        // used in a context where it is needed
134        public List<RolapMember> getLevelMembersFromCache(
135            RolapLevel level,
136            TupleConstraint constraint)
137        {
138            return null;
139        }
140    
141        public RolapMember lookupMember(
142            List<Id.Segment> uniqueNameParts,
143            boolean failIfNotFound)
144        {
145            return RolapUtil.lookupMember(this, uniqueNameParts, failIfNotFound);
146        }
147    
148        public List<RolapMember> getRootMembers() {
149            List<RolapMember> list = new ArrayList<RolapMember>();
150            for (RolapMember member : members) {
151                if (member.getParentUniqueName() == null) {
152                    list.add(member);
153                }
154            }
155            return list;
156        }
157    
158        public List<RolapMember> getMembersInLevel(
159            RolapLevel level,
160            int startOrdinal,
161            int endOrdinal)
162        {
163            List<RolapMember> list = new ArrayList<RolapMember>();
164            int levelDepth = level.getDepth();
165            for (RolapMember member : members) {
166                if ((member.getLevel().getDepth() == levelDepth) &&
167                    (startOrdinal <= member.getOrdinal()) &&
168                    (member.getOrdinal() < endOrdinal)) {
169    
170                    list.add(member);
171                }
172            }
173            return list;
174        }
175    
176        public List<RolapMember> getMembersInLevel(
177            RolapLevel level,
178            int startOrdinal,
179            int endOrdinal,
180            TupleConstraint constraint)
181        {
182            return getMembersInLevel(level, startOrdinal, endOrdinal);
183        }
184    
185        public int getLevelMemberCount(RolapLevel level) {
186            int count = 0;
187            int levelDepth = level.getDepth();
188            for (Member member : members) {
189                if (member.getLevel().getDepth() == levelDepth) {
190                    ++count;
191                }
192            }
193            return count;
194        }
195    
196        public void getMemberChildren(
197            RolapMember parentMember,
198            List<RolapMember> children)
199        {
200            for (Member member : members) {
201                if (member.getParentMember() == parentMember) {
202                    ((List)children).add(member);
203                }
204            }
205        }
206    
207        public void getMemberChildren(
208            RolapMember member,
209            List<RolapMember> children,
210            MemberChildrenConstraint constraint)
211        {
212            getMemberChildren(member, children);
213        }
214    
215        public void getMemberChildren(
216            List<RolapMember> parentMembers,
217            List<RolapMember> children) {
218            for (Member member : members) {
219                if (parentMembers.contains(member.getParentMember())) {
220                    ((List)children).add(member);
221                }
222            }
223        }
224    
225        public void getMemberChildren(
226            List<RolapMember> parentMembers,
227            List<RolapMember> children,
228            MemberChildrenConstraint constraint)
229        {
230            getMemberChildren(parentMembers, children);
231        }
232    
233        public RolapMember getLeadMember(RolapMember member, int n) {
234            if (n >= 0) {
235                for (int ordinal = member.getOrdinal(); ordinal < members.size();
236                     ordinal++) {
237                    if ((members.get(ordinal).getLevel() == member.getLevel()) &&
238                        (n-- == 0)) {
239    
240                        return members.get(ordinal);
241                    }
242                }
243                return (RolapMember) member.getHierarchy().getNullMember();
244    
245            } else {
246                for (int ordinal = member.getOrdinal(); ordinal >= 0; ordinal--) {
247                    if ((members.get(ordinal).getLevel() == member.getLevel()) &&
248                        (n++ == 0)) {
249                        return members.get(ordinal);
250                    }
251                }
252                return (RolapMember) member.getHierarchy().getNullMember();
253            }
254        }
255    
256        public void getMemberRange(
257            RolapLevel level,
258            RolapMember startMember,
259            RolapMember endMember,
260            List<RolapMember> list)
261        {
262            assert startMember != null;
263            assert endMember != null;
264            assert startMember.getLevel() == endMember.getLevel();
265            final int endOrdinal = endMember.getOrdinal();
266            for (int i = startMember.getOrdinal(); i <= endOrdinal; i++) {
267                if (members.get(i).getLevel() == endMember.getLevel()) {
268                    list.add(members.get(i));
269                }
270            }
271        }
272    
273        public int getMemberCount() {
274            return members.size();
275        }
276    
277        public int compare(RolapMember m1, RolapMember m2, boolean siblingsAreEqual) {
278            if (m1 == m2) {
279                return 0;
280            }
281            if (siblingsAreEqual &&
282                (m1.getParentMember() == m2.getParentMember())) {
283                return 0;
284            }
285            Util.assertTrue(members.get(m1.getOrdinal()) == m1);
286            Util.assertTrue(members.get(m2.getOrdinal()) == m2);
287    
288            return (m1.getOrdinal() < m2.getOrdinal()) ? -1 : 1;
289        }
290    
291        public MemberBuilder getMemberBuilder() {
292            return null;
293        }
294    
295        public RolapMember getDefaultMember() {
296            RolapMember defaultMember =
297                (RolapMember) getHierarchy().getDefaultMember();
298            if (defaultMember != null) {
299                return defaultMember;
300            }
301            return getRootMembers().get(0);
302        }
303    
304        public RolapMember getMemberParent(RolapMember member) {
305            return member.getParentMember();
306        }
307    }
308    
309    // End CacheMemberReader.java